implemented generic templates

This commit is contained in:
Araq
2012-08-27 01:59:14 +02:00
parent 08d0003ed0
commit 6bcdb9c8f4
7 changed files with 47 additions and 26 deletions

View File

@@ -86,8 +86,6 @@ proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
include semtempl
proc evalTypedExpr(c: PContext, e: PNode): PNode =
result = getConstExpr(c.module, e)
if result == nil:
@@ -154,7 +152,7 @@ proc semConstBoolExpr(c: PContext, n: PNode): PNode =
LocalError(n.info, errConstExprExpected)
result = nn
include semtypes, semexprs, semgnrc, semstmts
include semtypes, semtempl, semexprs, semgnrc, semstmts
proc addCodeForGenerics(c: PContext, n: PNode) =
for i in countup(c.generics.lastGenericIdx, Len(c.generics.generics) - 1):

View File

@@ -133,7 +133,10 @@ proc applyConcreteTypesToSig(genericProc: PSym, concTypes: seq[PType]): PType =
if i > 0: result.n.sons[i] = sig.n.sons[i]
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
if c.InstCounter > 1000: InternalError(fn.ast.info, "nesting too deep")
inc(c.InstCounter)

View File

@@ -517,13 +517,12 @@ proc semTry(c: PContext, n: PNode): PNode =
a.sons[length - 1] = semStmtScope(c, a.sons[length - 1])
dec c.p.inTryStmt
proc addGenericParamListToScope(c: PContext, n: PNode) =
if n.kind != nkGenericParams:
InternalError(n.info, "addGenericParamListToScope")
for i in countup(0, sonsLen(n)-1):
proc addGenericParamListToScope(c: PContext, n: PNode) =
if n.kind != nkGenericParams: illFormedAst(n)
for i in countup(0, sonsLen(n)-1):
var a = n.sons[i]
if a.kind == nkSym: addDecl(c, a.sym)
else: internalError(a.info, "addGenericParamListToScope")
else: illFormedAst(a)
proc typeSectionLeftSidePass(c: PContext, n: PNode) =
# 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) =
for i in countup(1, sonsLen(n)-1):
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) =
# search for the correct alias:

View File

@@ -183,8 +183,9 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
result = newSymNode(s, n.info)
elif Contains(c.toBind, s.id):
result = symChoice(c.c, n, s, scClosed)
elif s.owner == c.owner:
InternalAssert sfGenSym in s.flags
elif s.owner == c.owner and sfGenSym in s.flags:
# template tmp[T](x: var seq[T]) =
# var yz: T
incl(s.flags, sfUsed)
result = newSymNode(s, n.info)
of nkBind:
@@ -364,21 +365,32 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
n.sons[namePos] = newSymNode(s, n.sons[namePos].info)
if n.sons[pragmasPos].kind != nkEmpty:
pragma(c, s, n.sons[pragmasPos], templatePragmas)
# check that no generic parameters exist:
var gp: PNode
if n.sons[genericParamsPos].kind != nkEmpty:
LocalError(n.info, errNoGenericParamsAllowedForX, "template")
if n.sons[paramsPos].kind == nkEmpty:
# 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]))
n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos])
gp = n.sons[genericParamsPos]
else:
semParamList(c, n.sons[ParamsPos], nil, s)
if n.sons[paramsPos].sons[0].kind == nkEmpty:
gp = newNodeI(nkGenericParams, n.info)
# 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
s.typ.sons[0] = newTypeS(tyStmt, c)
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
ctx.toBind = initIntSet()
ctx.c = c

View File

@@ -138,8 +138,8 @@ proc NotFoundError*(c: PContext, n: PNode) =
var candidates = ""
var o: TOverloadIter
var sym = initOverloadIter(o, c, n.sons[0])
while sym != nil:
if sym.kind in {skProc, skMethod, skIterator, skConverter}:
while sym != nil:
if sym.kind in RoutineKinds:
add(candidates, getProcHeader(sym))
add(candidates, "\n")
#debug(sym.typ)

View 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

View File

@@ -1,9 +1,8 @@
version 0.9.0
=============
- make 'bind' default for templates and introduce 'mixin'
- 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 for loop transformation for first class iterators
@@ -37,6 +36,8 @@ version 0.9.XX
- fix exception handling
- 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;
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