mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-12 22:33:49 +00:00
improvements for 'bind', fixes #166
This commit is contained in:
@@ -1412,13 +1412,12 @@ proc parseBind(p: var TParser): PNode =
|
||||
result = newNodeP(nkBindStmt, p)
|
||||
getTok(p)
|
||||
optInd(p, result)
|
||||
while p.tok.tokType == tkSymbol:
|
||||
var a = newIdentNodeP(p.tok.ident, p)
|
||||
getTok(p)
|
||||
while true:
|
||||
var a = qualifiedIdent(p)
|
||||
addSon(result, a)
|
||||
if p.tok.tokType != tkComma: break
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
optInd(p, a)
|
||||
optInd(p, a)
|
||||
expectNl(p)
|
||||
|
||||
proc parseStmtPragma(p: var TParser): PNode =
|
||||
|
||||
@@ -13,12 +13,12 @@ proc symChoice(c: PContext, n: PNode, s: PSym): PNode =
|
||||
var
|
||||
a: PSym
|
||||
o: TOverloadIter
|
||||
i: int
|
||||
i = 0
|
||||
var i = 0
|
||||
a = initOverloadIter(o, c, n)
|
||||
while a != nil:
|
||||
a = nextOverloadIter(o, c, n)
|
||||
inc(i)
|
||||
if i > 1: break
|
||||
if i <= 1:
|
||||
result = newSymNode(s)
|
||||
result.info = n.info
|
||||
@@ -36,41 +36,45 @@ proc symChoice(c: PContext, n: PNode, s: PSym): PNode =
|
||||
proc semBindStmt(c: PContext, n: PNode, toBind: var TIntSet): PNode =
|
||||
for i in 0 .. < n.len:
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkIdent:
|
||||
var s = SymtabGet(c.Tab, a.ident)
|
||||
if s != nil:
|
||||
toBind.incl(s.name.id)
|
||||
else:
|
||||
localError(a.info, errUndeclaredIdentifier, a.ident.s)
|
||||
else:
|
||||
# If 'a' is an overloaded symbol, we use the first symbol as a 'witness'
|
||||
# and use the fact that subsequent lookups will yield the same symbol!
|
||||
# This is currently the case due to the hash table's implementation...
|
||||
let s = QualifiedLookUp(c, a)
|
||||
if s != nil:
|
||||
toBind.incl(s.id)
|
||||
else:
|
||||
illFormedAst(a)
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
|
||||
proc resolveTemplateParams(c: PContext, n: PNode, withinBind: bool,
|
||||
proc resolveTemplateParams(c: PContext, n: PNode, owner: PSym,
|
||||
toBind: var TIntSet): PNode =
|
||||
var s: PSym
|
||||
case n.kind
|
||||
of nkIdent:
|
||||
if not withinBind and not Contains(toBind, n.ident.id):
|
||||
s = SymTabLocalGet(c.Tab, n.ident)
|
||||
if s != nil:
|
||||
of nkIdent, nkAccQuoted:
|
||||
result = n
|
||||
let s = QualifiedLookUp(c, n, {})
|
||||
if s != nil:
|
||||
if s.owner == owner and s.kind == skParam:
|
||||
result = newSymNode(s)
|
||||
result.info = n.info
|
||||
else:
|
||||
result = n
|
||||
else:
|
||||
Incl(toBind, n.ident.id)
|
||||
result = symChoice(c, n, lookup(c, n))
|
||||
elif Contains(toBind, s.id):
|
||||
result = symChoice(c, n, s)
|
||||
of nkEmpty, nkSym..nkNilLit: # atom
|
||||
result = n
|
||||
of nkBind:
|
||||
result = resolveTemplateParams(c, n.sons[0], true, toBind)
|
||||
of nkBind:
|
||||
result = resolveTemplateParams(c, n.sons[0], owner, toBind)
|
||||
of nkBindStmt:
|
||||
result = semBindStmt(c, n, toBind)
|
||||
else:
|
||||
else:
|
||||
# dotExpr is ambiguous: note that we explicitely allow 'x.TemplateParam',
|
||||
# so we use the generic code for nkDotExpr too
|
||||
if n.kind == nkDotExpr:
|
||||
let s = QualifiedLookUp(c, n, {})
|
||||
if s != nil and Contains(toBind, s.id):
|
||||
return symChoice(c, n, s)
|
||||
result = n
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
result.sons[i] = resolveTemplateParams(c, n.sons[i], withinBind, toBind)
|
||||
result.sons[i] = resolveTemplateParams(c, n.sons[i], owner, toBind)
|
||||
|
||||
proc transformToExpr(n: PNode): PNode =
|
||||
var realStmt: int
|
||||
@@ -122,7 +126,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||
s.typ.sons[0] = newTypeS(tyStmt, c)
|
||||
s.typ.n.sons[0] = newNodeIT(nkType, n.info, s.typ.sons[0])
|
||||
var toBind = initIntSet()
|
||||
n.sons[bodyPos] = resolveTemplateParams(c, n.sons[bodyPos], false, toBind)
|
||||
n.sons[bodyPos] = resolveTemplateParams(c, n.sons[bodyPos], s, toBind)
|
||||
if s.typ.sons[0].kind notin {tyStmt, tyTypeDesc}:
|
||||
n.sons[bodyPos] = transformToExpr(n.sons[bodyPos])
|
||||
# only parameters are resolved, no type checking is performed
|
||||
|
||||
@@ -137,7 +137,7 @@ staticStmt ::= 'static' ':' stmt
|
||||
filename ::= symbol | STR_LIT | RSTR_LIT | TRIPLESTR_LIT
|
||||
importStmt ::= 'import' filename (comma filename)*
|
||||
includeStmt ::= 'include' filename (comma filename)*
|
||||
bindStmt ::= 'bind' IDENT (comma IDENT)*
|
||||
bindStmt ::= 'bind' qualifiedIdent (comma qualifiedIdent)*
|
||||
fromStmt ::= 'from' filename 'import' symbol (comma symbol)*
|
||||
|
||||
pragma ::= '{.' optInd (colonExpr [comma])* optPar ('.}' | '}')
|
||||
|
||||
24
tests/run/tstempl.nim
Normal file
24
tests/run/tstempl.nim
Normal file
@@ -0,0 +1,24 @@
|
||||
discard """
|
||||
output: '''global = levB, arg = levA, test = false
|
||||
levB'''
|
||||
"""
|
||||
|
||||
# tstempl.nim
|
||||
import strutils
|
||||
|
||||
type
|
||||
TLev = enum
|
||||
levA,
|
||||
levB
|
||||
|
||||
var abclev = levB
|
||||
|
||||
template tstLev(abclev: TLev) =
|
||||
bind tstempl.abclev, `%`
|
||||
writeln(stdout, "global = $1, arg = $2, test = $3" % [
|
||||
$tstempl.abclev, $abclev, $(tstempl.abclev == abclev)])
|
||||
# evaluates to true, but must be false
|
||||
|
||||
|
||||
tstLev(levA)
|
||||
writeln(stdout, $abclev)
|
||||
3
todo.txt
3
todo.txt
@@ -2,7 +2,6 @@ version 0.9.0
|
||||
=============
|
||||
|
||||
- fix DLLs
|
||||
- fix 'bind' for templates
|
||||
- implicit deref for parameter matching
|
||||
- deprecate ``var x, y = 0`` as it's confusing for tuple consistency
|
||||
|
||||
@@ -35,7 +34,7 @@ Bugs
|
||||
but this can lead to compilation errors
|
||||
- bug: the parser is not strict enough with newlines: 'echo "a" echo "b"'
|
||||
compiles
|
||||
|
||||
- bug: blocks can "export" an identifier but the CCG generates {} for them ...
|
||||
|
||||
version 0.9.XX
|
||||
==============
|
||||
|
||||
@@ -95,6 +95,8 @@ Changes affecting backwards compatibility
|
||||
conversions from ``int`` to ``int32`` are now forbidden.
|
||||
- ``system.byte`` is now an alias for ``uint8``; it used to be an alias
|
||||
to ``int8``.
|
||||
- ``bind`` expressions in templates are not properly supported anymore. Use
|
||||
the declarative ``bind`` statement instead.
|
||||
|
||||
|
||||
Compiler Additions
|
||||
@@ -136,6 +138,7 @@ Language Additions
|
||||
readability: ``proc divmod(a, b: int; resA, resB: var int)``.
|
||||
- A semicolon can now be used to have multiple simple statements on a single
|
||||
line: ``inc i; inc j``.
|
||||
- ``bind`` supports overloaded symbols and operators.
|
||||
|
||||
|
||||
2012-02-09 Version 0.8.14 released
|
||||
|
||||
Reference in New Issue
Block a user