stricter symbol lookup in generics

This commit is contained in:
Araq 2012-09-17 17:01:34 +02:00
commit c934db86ad
6 changed files with 19 additions and 20 deletions

View file

@ -80,15 +80,13 @@ proc semGenericStmt(c: PContext, n: PNode,
of nkIdent, nkAccQuoted: of nkIdent, nkAccQuoted:
var s = SymtabGet(c.Tab, n.ident) var s = SymtabGet(c.Tab, n.ident)
if s == nil: if s == nil:
# no error if symbol cannot be bound, unless in ``bind`` context: localError(n.info, errUndeclaredIdentifier, n.ident.s)
if withinBind in flags:
localError(n.info, errUndeclaredIdentifier, n.ident.s)
else: else:
if withinBind in flags or s.id in toBind: if withinBind in flags or s.id in toBind:
result = symChoice(c, n, s, scClosed) result = symChoice(c, n, s, scClosed)
else: result = semGenericStmtSymbol(c, n, s) else: result = semGenericStmtSymbol(c, n, s)
of nkDotExpr: of nkDotExpr:
var s = QualifiedLookUp(c, n, {}) var s = QualifiedLookUp(c, n, {checkUndeclared})
if s != nil: result = semGenericStmtSymbol(c, n, s) if s != nil: result = semGenericStmtSymbol(c, n, s)
# XXX for example: ``result.add`` -- ``add`` needs to be looked up here... # XXX for example: ``result.add`` -- ``add`` needs to be looked up here...
of nkEmpty, nkSym..nkNilLit: of nkEmpty, nkSym..nkNilLit:
@ -100,10 +98,12 @@ proc semGenericStmt(c: PContext, n: PNode,
of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkCommand, nkCallStrLit: of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkCommand, nkCallStrLit:
# check if it is an expression macro: # check if it is an expression macro:
checkMinSonsLen(n, 1) checkMinSonsLen(n, 1)
var s = qualifiedLookup(c, n.sons[0], {}) var s = qualifiedLookup(c, n.sons[0], {checkUndeclared})
var first = 0 var first = 0
var isDefinedMagic = false
if s != nil: if s != nil:
incl(s.flags, sfUsed) incl(s.flags, sfUsed)
isDefinedMagic = s.magic in {mDefined, mDefinedInScope, mCompiles}
case s.kind case s.kind
of skMacro: of skMacro:
if macroToExpand(s): if macroToExpand(s):
@ -135,14 +135,15 @@ proc semGenericStmt(c: PContext, n: PNode,
else: else:
result.sons[0] = newSymNode(s, n.sons[0].info) result.sons[0] = newSymNode(s, n.sons[0].info)
first = 1 first = 1
for i in countup(first, sonsLen(result) - 1): if not isDefinedMagic:
result.sons[i] = semGenericStmt(c, result.sons[i], flags, toBind) for i in countup(first, sonsLen(result) - 1):
result.sons[i] = semGenericStmt(c, result.sons[i], flags, toBind)
of nkMacroStmt: of nkMacroStmt:
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2)
var a: PNode var a: PNode
if isCallExpr(n.sons[0]): a = n.sons[0].sons[0] if isCallExpr(n.sons[0]): a = n.sons[0].sons[0]
else: a = n.sons[0] else: a = n.sons[0]
var s = qualifiedLookup(c, a, {}) var s = qualifiedLookup(c, a, {checkUndeclared})
if s != nil and macroToExpand(s): if s != nil and macroToExpand(s):
result = semMacroStmt(c, n, {}, false) result = semMacroStmt(c, n, {}, false)
for i in countup(0, sonsLen(result)-1): for i in countup(0, sonsLen(result)-1):
@ -287,6 +288,7 @@ proc semGenericStmt(c: PContext, n: PNode,
else: body = n.sons[bodyPos] else: body = n.sons[bodyPos]
n.sons[bodyPos] = semGenericStmtScope(c, body, flags, toBind) n.sons[bodyPos] = semGenericStmtScope(c, body, flags, toBind)
closeScope(c.tab) closeScope(c.tab)
of nkPragma, nkPragmaExpr: nil
else: else:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
result.sons[i] = semGenericStmt(c, n.sons[i], flags, toBind) result.sons[i] = semGenericStmt(c, n.sons[i], flags, toBind)

View file

@ -48,7 +48,7 @@ var
totalCalls = 0 totalCalls = 0
var var
interval: TNanos = 1_000_000 - tickCountCorrection # 5ms interval: TNanos = 5_000_000 - tickCountCorrection # 5ms
proc setSamplingFrequency*(intervalInUs: int) = proc setSamplingFrequency*(intervalInUs: int) =
## set this to change the sampling frequency. Default value is 5ms. ## set this to change the sampling frequency. Default value is 5ms.

View file

@ -168,9 +168,6 @@ proc `..`*[T](b: T): TSlice[T] {.noSideEffect, inline.} =
## `slice`:idx: operator that constructs an interval ``[default(T), b]`` ## `slice`:idx: operator that constructs an interval ``[default(T), b]``
result.b = b result.b = b
proc contains*[T](s: TSlice[T], value: T): bool {.noSideEffect, inline.} =
result = value >= s.a and value <= s.b
when not defined(niminheritable): when not defined(niminheritable):
{.pragma: inheritable.} {.pragma: inheritable.}
@ -672,6 +669,9 @@ proc contains*[T](x: set[T], y: T): bool {.magic: "InSet", noSideEffect.}
## is achieved by reversing the parameters for ``contains``; ``in`` then ## is achieved by reversing the parameters for ``contains``; ``in`` then
## passes its arguments in reverse order. ## passes its arguments in reverse order.
proc contains*[T](s: TSlice[T], value: T): bool {.noSideEffect, inline.} =
result = s.a <= value and value <= s.b
template `in` * (x, y: expr): expr {.immediate.} = contains(y, x) template `in` * (x, y: expr): expr {.immediate.} = contains(y, x)
template `not_in` * (x, y: expr): expr {.immediate.} = not contains(y, x) template `not_in` * (x, y: expr): expr {.immediate.} = not contains(y, x)

View file

@ -144,6 +144,8 @@ proc objectInit(dest: Pointer, typ: PNimType) =
# ---------------------- assign zero ----------------------------------------- # ---------------------- assign zero -----------------------------------------
# dummy declaration; XXX we need 'mixin' here
proc destroy(x: int) = nil
proc nimDestroyRange*[T](r: T) = proc nimDestroyRange*[T](r: T) =
# internal proc used for destroying sequences and arrays # internal proc used for destroying sequences and arrays
for i in countup(0, r.len - 1): destroy(r[i]) for i in countup(0, r.len - 1): destroy(r[i])

View file

@ -11,10 +11,7 @@
# code generator. The idea is to inject the instruction stream # code generator. The idea is to inject the instruction stream
# with 'nimProfile()' calls. These calls are injected at every loop end # with 'nimProfile()' calls. These calls are injected at every loop end
# (except perhaps loops that have no side-effects). At every Nth call a # (except perhaps loops that have no side-effects). At every Nth call a
# stack trace is taken. A stack tace is a list of cstrings. We have a count # stack trace is taken. A stack tace is a list of cstrings.
# table of those.
#
# The nice thing about this profiler is that it's completely time independent!
{.push profiler: off.} {.push profiler: off.}

View file

@ -2,12 +2,10 @@ version 0.9.0
============= =============
- make 'bind' default for templates and introduce 'mixin' - make 'bind' default for templates and introduce 'mixin'
- make 'm: stmt' use overloading resolution
- implicit deref for parameter matching - implicit deref for parameter matching
- optimize genericAssign in the code generator - optimize genericAssign in the code generator
- the lookup rules for generics really are too permissive; global scope only
doesn't fly with closures though; for a start add a warning when processing
generic code
Bugs Bugs
@ -38,7 +36,7 @@ version 0.9.XX
echo a echo a
echo b) echo b)
- make 'm: stmt' use overloading resolution - implement the "snoopResult" pragma
- 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
- JS gen: - JS gen: