implemented generic templates
This commit is contained in:
parent
08d0003ed0
commit
6bcdb9c8f4
7 changed files with 47 additions and 26 deletions
|
|
@ -86,8 +86,6 @@ proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
|
||||||
|
|
||||||
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
|
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
|
||||||
|
|
||||||
include semtempl
|
|
||||||
|
|
||||||
proc evalTypedExpr(c: PContext, e: PNode): PNode =
|
proc evalTypedExpr(c: PContext, e: PNode): PNode =
|
||||||
result = getConstExpr(c.module, e)
|
result = getConstExpr(c.module, e)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
|
|
@ -154,7 +152,7 @@ proc semConstBoolExpr(c: PContext, n: PNode): PNode =
|
||||||
LocalError(n.info, errConstExprExpected)
|
LocalError(n.info, errConstExprExpected)
|
||||||
result = nn
|
result = nn
|
||||||
|
|
||||||
include semtypes, semexprs, semgnrc, semstmts
|
include semtypes, semtempl, semexprs, semgnrc, semstmts
|
||||||
|
|
||||||
proc addCodeForGenerics(c: PContext, n: PNode) =
|
proc addCodeForGenerics(c: PContext, n: PNode) =
|
||||||
for i in countup(c.generics.lastGenericIdx, Len(c.generics.generics) - 1):
|
for i in countup(c.generics.lastGenericIdx, Len(c.generics.generics) - 1):
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,10 @@ proc applyConcreteTypesToSig(genericProc: PSym, concTypes: seq[PType]): PType =
|
||||||
if i > 0: result.n.sons[i] = sig.n.sons[i]
|
if i > 0: result.n.sons[i] = sig.n.sons[i]
|
||||||
|
|
||||||
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
info: TLineInfo): PSym =
|
info: TLineInfo): PSym =
|
||||||
|
# no need to instantiate generic templates/macros:
|
||||||
|
if fn.kind in {skTemplate, skMacro}: return fn
|
||||||
|
|
||||||
# generates an instantiated proc
|
# generates an instantiated proc
|
||||||
if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep")
|
if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep")
|
||||||
inc(c.InstCounter)
|
inc(c.InstCounter)
|
||||||
|
|
|
||||||
|
|
@ -517,13 +517,12 @@ proc semTry(c: PContext, n: PNode): PNode =
|
||||||
a.sons[length - 1] = semStmtScope(c, a.sons[length - 1])
|
a.sons[length - 1] = semStmtScope(c, a.sons[length - 1])
|
||||||
dec c.p.inTryStmt
|
dec c.p.inTryStmt
|
||||||
|
|
||||||
proc addGenericParamListToScope(c: PContext, n: PNode) =
|
proc addGenericParamListToScope(c: PContext, n: PNode) =
|
||||||
if n.kind != nkGenericParams:
|
if n.kind != nkGenericParams: illFormedAst(n)
|
||||||
InternalError(n.info, "addGenericParamListToScope")
|
for i in countup(0, sonsLen(n)-1):
|
||||||
for i in countup(0, sonsLen(n)-1):
|
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
if a.kind == nkSym: addDecl(c, a.sym)
|
if a.kind == nkSym: addDecl(c, a.sym)
|
||||||
else: internalError(a.info, "addGenericParamListToScope")
|
else: illFormedAst(a)
|
||||||
|
|
||||||
proc typeSectionLeftSidePass(c: PContext, n: PNode) =
|
proc typeSectionLeftSidePass(c: PContext, n: PNode) =
|
||||||
# process the symbols on the left side for the whole type section, before
|
# process the symbols on the left side for the whole type section, before
|
||||||
|
|
@ -635,7 +634,7 @@ proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) =
|
||||||
proc addParams(c: PContext, n: PNode, kind: TSymKind) =
|
proc addParams(c: PContext, n: PNode, kind: TSymKind) =
|
||||||
for i in countup(1, sonsLen(n)-1):
|
for i in countup(1, sonsLen(n)-1):
|
||||||
if n.sons[i].kind == nkSym: addParamOrResult(c, n.sons[i].sym, kind)
|
if n.sons[i].kind == nkSym: addParamOrResult(c, n.sons[i].sym, kind)
|
||||||
else: InternalError(n.info, "addParams")
|
else: illFormedAst(n)
|
||||||
|
|
||||||
proc semBorrow(c: PContext, n: PNode, s: PSym) =
|
proc semBorrow(c: PContext, n: PNode, s: PSym) =
|
||||||
# search for the correct alias:
|
# search for the correct alias:
|
||||||
|
|
|
||||||
|
|
@ -183,8 +183,9 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
elif Contains(c.toBind, s.id):
|
elif Contains(c.toBind, s.id):
|
||||||
result = symChoice(c.c, n, s, scClosed)
|
result = symChoice(c.c, n, s, scClosed)
|
||||||
elif s.owner == c.owner:
|
elif s.owner == c.owner and sfGenSym in s.flags:
|
||||||
InternalAssert sfGenSym in s.flags
|
# template tmp[T](x: var seq[T]) =
|
||||||
|
# var yz: T
|
||||||
incl(s.flags, sfUsed)
|
incl(s.flags, sfUsed)
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
of nkBind:
|
of nkBind:
|
||||||
|
|
@ -364,21 +365,32 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||||
n.sons[namePos] = newSymNode(s, n.sons[namePos].info)
|
n.sons[namePos] = newSymNode(s, n.sons[namePos].info)
|
||||||
if n.sons[pragmasPos].kind != nkEmpty:
|
if n.sons[pragmasPos].kind != nkEmpty:
|
||||||
pragma(c, s, n.sons[pragmasPos], templatePragmas)
|
pragma(c, s, n.sons[pragmasPos], templatePragmas)
|
||||||
# check that no generic parameters exist:
|
|
||||||
|
var gp: PNode
|
||||||
if n.sons[genericParamsPos].kind != nkEmpty:
|
if n.sons[genericParamsPos].kind != nkEmpty:
|
||||||
LocalError(n.info, errNoGenericParamsAllowedForX, "template")
|
n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos])
|
||||||
if n.sons[paramsPos].kind == nkEmpty:
|
gp = n.sons[genericParamsPos]
|
||||||
# use ``stmt`` as implicit result type
|
|
||||||
s.typ = newTypeS(tyProc, c)
|
|
||||||
s.typ.n = newNodeI(nkFormalParams, n.info)
|
|
||||||
rawAddSon(s.typ, newTypeS(tyStmt, c))
|
|
||||||
addSon(s.typ.n, newNodeIT(nkType, n.info, s.typ.sons[0]))
|
|
||||||
else:
|
else:
|
||||||
semParamList(c, n.sons[ParamsPos], nil, s)
|
gp = newNodeI(nkGenericParams, n.info)
|
||||||
if n.sons[paramsPos].sons[0].kind == nkEmpty:
|
# process parameters:
|
||||||
|
if n.sons[paramsPos].kind != nkEmpty:
|
||||||
|
semParamList(c, n.sons[ParamsPos], gp, s)
|
||||||
|
if sonsLen(gp) > 0:
|
||||||
|
if n.sons[genericParamsPos].kind == nkEmpty:
|
||||||
|
# we have a list of implicit type parameters:
|
||||||
|
n.sons[genericParamsPos] = gp
|
||||||
|
# no explicit return type? -> use tyStmt
|
||||||
|
if n.sons[paramsPos].sons[0].kind == nkEmpty:
|
||||||
# use ``stmt`` as implicit result type
|
# use ``stmt`` as implicit result type
|
||||||
s.typ.sons[0] = newTypeS(tyStmt, c)
|
s.typ.sons[0] = newTypeS(tyStmt, c)
|
||||||
s.typ.n.sons[0] = newNodeIT(nkType, n.info, s.typ.sons[0])
|
s.typ.n.sons[0] = newNodeIT(nkType, n.info, s.typ.sons[0])
|
||||||
|
else:
|
||||||
|
s.typ = newTypeS(tyProc, c)
|
||||||
|
# XXX why do we need tyStmt as a return type again?
|
||||||
|
s.typ.n = newNodeI(nkFormalParams, n.info)
|
||||||
|
rawAddSon(s.typ, newTypeS(tyStmt, c))
|
||||||
|
addSon(s.typ.n, newNodeIT(nkType, n.info, s.typ.sons[0]))
|
||||||
|
|
||||||
var ctx: TemplCtx
|
var ctx: TemplCtx
|
||||||
ctx.toBind = initIntSet()
|
ctx.toBind = initIntSet()
|
||||||
ctx.c = c
|
ctx.c = c
|
||||||
|
|
|
||||||
|
|
@ -138,8 +138,8 @@ proc NotFoundError*(c: PContext, n: PNode) =
|
||||||
var candidates = ""
|
var candidates = ""
|
||||||
var o: TOverloadIter
|
var o: TOverloadIter
|
||||||
var sym = initOverloadIter(o, c, n.sons[0])
|
var sym = initOverloadIter(o, c, n.sons[0])
|
||||||
while sym != nil:
|
while sym != nil:
|
||||||
if sym.kind in {skProc, skMethod, skIterator, skConverter}:
|
if sym.kind in RoutineKinds:
|
||||||
add(candidates, getProcHeader(sym))
|
add(candidates, getProcHeader(sym))
|
||||||
add(candidates, "\n")
|
add(candidates, "\n")
|
||||||
#debug(sym.typ)
|
#debug(sym.typ)
|
||||||
|
|
|
||||||
8
tests/compile/tgenerictmpl.nim
Normal file
8
tests/compile/tgenerictmpl.nim
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
template tmp[T](x: var seq[T]) =
|
||||||
|
var yz: T
|
||||||
|
x = @[1, 2, 3]
|
||||||
|
|
||||||
|
var y: seq[int]
|
||||||
|
tmp(y)
|
||||||
|
echo y.repr
|
||||||
5
todo.txt
5
todo.txt
|
|
@ -1,9 +1,8 @@
|
||||||
version 0.9.0
|
version 0.9.0
|
||||||
=============
|
=============
|
||||||
|
|
||||||
- make 'bind' default for templates and introduce 'mixin'
|
|
||||||
- introduce 'callsite' magic and make macros and templates the same
|
- introduce 'callsite' magic and make macros and templates the same
|
||||||
- implement generic templates/macros
|
- make 'bind' default for templates and introduce 'mixin'
|
||||||
|
|
||||||
- implement "closure tuple consists of a single 'ref'" optimization
|
- implement "closure tuple consists of a single 'ref'" optimization
|
||||||
- implement for loop transformation for first class iterators
|
- implement for loop transformation for first class iterators
|
||||||
|
|
@ -37,6 +36,8 @@ version 0.9.XX
|
||||||
- fix exception handling
|
- fix exception handling
|
||||||
|
|
||||||
- document 'do' notation
|
- document 'do' notation
|
||||||
|
- allow implicit forward declarations of procs via a pragma (so that the
|
||||||
|
wrappers can deactivate it)
|
||||||
- rethink the syntax: distinction between expr and stmt is unfortunate;
|
- rethink the syntax: distinction between expr and stmt is unfortunate;
|
||||||
indentation handling is quite complex too; problem with exception handling
|
indentation handling is quite complex too; problem with exception handling
|
||||||
is that often the scope of ``try`` is wrong and apart from that ``try`` is
|
is that often the scope of ``try`` is wrong and apart from that ``try`` is
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue