mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-31 10:22:15 +00:00
implemented generic templates
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
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
|
||||
=============
|
||||
|
||||
- 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
|
||||
|
||||
Reference in New Issue
Block a user