diff options
author | Araq <rumpf_a@web.de> | 2014-02-04 17:29:34 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-02-04 17:29:34 +0100 |
commit | c097acedd30602fba903ed4ee132b5e5bae91017 (patch) | |
tree | 9f9699827b48c3c0d3b2c98b19881c361467a239 | |
parent | 96e616198d100f0e10337c0210b088730d66d91e (diff) | |
download | Nim-c097acedd30602fba903ed4ee132b5e5bae91017.tar.gz |
bugfix: immediate templates are preferred consistently (danger: breaks code)
-rw-r--r-- | compiler/astalgo.nim | 33 | ||||
-rw-r--r-- | compiler/lookups.nim | 14 | ||||
-rw-r--r-- | tests/template/tprefer_immediate.nim | 17 | ||||
-rw-r--r-- | todo.txt | 1 |
4 files changed, 55 insertions, 10 deletions
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index 2505bc687..64c1b717c 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -561,14 +561,31 @@ proc strTableContains(t: TStrTable, n: PSym): bool = proc strTableRawInsert(data: var TSymSeq, n: PSym) = var h: THash = n.name.h and high(data) - while data[h] != nil: - if data[h] == n: - # allowed for 'export' feature: - #InternalError(n.info, "StrTableRawInsert: " & n.name.s) - return - h = nextTry(h, high(data)) - assert(data[h] == nil) - data[h] = n + if sfImmediate notin n.flags: + # fast path: + while data[h] != nil: + if data[h] == n: + # allowed for 'export' feature: + #InternalError(n.info, "StrTableRawInsert: " & n.name.s) + return + h = nextTry(h, high(data)) + assert(data[h] == nil) + data[h] = n + else: + # slow path; we have to ensure immediate symbols are preferred for + # symbol lookups. + # consider the chain: foo (immediate), foo, bar, bar (immediate) + # then bar (immediate) gets replaced with foo (immediate) and the non + # immediate foo is picked! Thus we need to replace it with the first + # slot that has in fact the same identifier stored in it! + var favPos = -1 + while data[h] != nil: + if data[h] == n: return + if favPos < 0 and data[h].name.id == n.name.id: favPos = h + h = nextTry(h, high(data)) + assert(data[h] == nil) + data[h] = n + if favPos >= 0: swap data[h], data[favPos] proc symTabReplaceRaw(data: var TSymSeq, prevSym: PSym, newSym: PSym) = assert prevSym.name.h == newSym.name.h diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 6dfd25968..c31eb3121 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -339,4 +339,16 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = n.sons[0].sym.name, o.inSymChoice) if result != nil and result.kind == skStub: loadStub(result) - + +when false: + proc qualifiedLookUpPreferImmediate*(c: PContext, n: PNode, + flags = {checkUndeclared}): PSym = + var o: TOverloadIter + result = initOverloadIter(o, c, n) + var a = result + while a != nil: + if sfImmediate in a.flags: return a + a = nextOverloadIter(o, c, n) + if result == nil and checkUndeclared in flags: + localError(n.info, errUndeclaredIdentifier, n.considerAcc.s) + result = errorSym(c, n) diff --git a/tests/template/tprefer_immediate.nim b/tests/template/tprefer_immediate.nim new file mode 100644 index 000000000..578f447b0 --- /dev/null +++ b/tests/template/tprefer_immediate.nim @@ -0,0 +1,17 @@ +discard """ + output: '''immediate''' +""" + +# Test that immediate templates are preferred over non-immediate templates + +template foo(a, b: expr) = echo "foo expr" + +template foo(a, b: int) = echo "foo int" +template foo(a, b: float) = echo "foo float" +template foo(a, b: string) = echo "foo string" +template foo(a, b: expr) {.immediate.} = echo "immediate" +template foo(a, b: bool) = echo "foo bool" +template foo(a, b: char) = echo "foo char" + +foo(undeclaredIdentifier, undeclaredIdentifier2) + diff --git a/todo.txt b/todo.txt index fd424ad5e..6f8726199 100644 --- a/todo.txt +++ b/todo.txt @@ -22,7 +22,6 @@ Bugs - compilation of niminst takes way too long. looks like a regression - docgen: sometimes effects are listed twice - 'result' is not properly cleaned for NRVO --> use uninit checking instead -- sneaking with qualifiedLookup() is really broken! - blocks can "export" an identifier but the CCG generates {} for them ... - osproc execProcesses can deadlock if all processes fail (as experienced in c++ mode) |