mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-20 14:25:23 +00:00
bugfix: 'when' sections in generic objects now work, so TThread[void] compiles
This commit is contained in:
@@ -1022,7 +1022,7 @@ proc getStr*(a: PNode): string =
|
||||
proc getStrOrChar*(a: PNode): string =
|
||||
case a.kind
|
||||
of nkStrLit..nkTripleStrLit: result = a.strVal
|
||||
of nkCharLit: result = chr(int(a.intVal)) & ""
|
||||
of nkCharLit: result = $chr(int(a.intVal))
|
||||
else:
|
||||
internalError(a.info, "getStrOrChar")
|
||||
result = ""
|
||||
|
||||
@@ -747,7 +747,7 @@ proc evalConStrStr(c: PEvalContext, n: PNode): PNode =
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
result = evalAux(c, n.sons[i], {})
|
||||
if isSpecial(result): return
|
||||
a.strVal.add(getStrValue(result))
|
||||
a.strVal.add(getStrOrChar(result))
|
||||
result = a
|
||||
|
||||
proc evalAppendStrStr(c: PEvalContext, n: PNode): PNode =
|
||||
@@ -758,7 +758,7 @@ proc evalAppendStrStr(c: PEvalContext, n: PNode): PNode =
|
||||
if isSpecial(result): return
|
||||
var b = result
|
||||
case a.kind
|
||||
of nkStrLit..nkTripleStrLit: a.strVal = a.strVal & getStrValue(b)
|
||||
of nkStrLit..nkTripleStrLit: a.strVal = a.strVal & getStrOrChar(b)
|
||||
else: InternalError(n.info, "evalAppendStrStr")
|
||||
result = emptyNode
|
||||
|
||||
|
||||
@@ -49,25 +49,26 @@ type
|
||||
PGenericsCache* = ref TGenericsCache
|
||||
PContext* = ref TContext
|
||||
TContext* = object of TPassContext # a context represents a module
|
||||
module*: PSym # the module sym belonging to the context
|
||||
p*: PProcCon # procedure context
|
||||
generics*: PGenericsCache # may point to a global or module-local structure
|
||||
friendModule*: PSym # current friend module; may access private data;
|
||||
# this is used so that generic instantiations can
|
||||
# access private object fields
|
||||
InstCounter*: int # to prevent endless instantiations
|
||||
module*: PSym # the module sym belonging to the context
|
||||
p*: PProcCon # procedure context
|
||||
generics*: PGenericsCache # may point to a global or module-local structure
|
||||
friendModule*: PSym # current friend module; may access private data;
|
||||
# this is used so that generic instantiations
|
||||
# can access private object fields
|
||||
InstCounter*: int # to prevent endless instantiations
|
||||
|
||||
threadEntries*: TSymSeq # list of thread entries to check
|
||||
tab*: TSymTab # each module has its own symbol table
|
||||
threadEntries*: TSymSeq # list of thread entries to check
|
||||
tab*: TSymTab # each module has its own symbol table
|
||||
AmbiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot
|
||||
# store this info in the syms themselves!)
|
||||
converters*: TSymSeq # sequence of converters
|
||||
InGenericContext*: int # > 0 if we are in a generic
|
||||
converters*: TSymSeq # sequence of converters
|
||||
optionStack*: TLinkedList
|
||||
libs*: TLinkedList # all libs used by this module
|
||||
libs*: TLinkedList # all libs used by this module
|
||||
semConstExpr*: proc (c: PContext, n: PNode): PNode # for the pragmas
|
||||
semExpr*: proc (c: PContext, n: PNode): PNode # for the pragmas
|
||||
includedFiles*: TIntSet # used to detect recursive include files
|
||||
filename*: string # the module's filename
|
||||
includedFiles*: TIntSet # used to detect recursive include files
|
||||
filename*: string # the module's filename
|
||||
userPragmas*: TStrTable
|
||||
evalContext*: PEvalContext
|
||||
slurpedFiles*: seq[string]
|
||||
@@ -91,8 +92,7 @@ proc makePtrType*(c: PContext, baseType: PType): PType
|
||||
proc makeVarType*(c: PContext, baseType: PType): PType
|
||||
proc newTypeS*(kind: TTypeKind, c: PContext): PType
|
||||
proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext)
|
||||
proc makeRangeType*(c: PContext, first, last: biggestInt, info: TLineInfo): PType
|
||||
|
||||
|
||||
# owner handling:
|
||||
proc getCurrOwner*(): PSym
|
||||
proc PushOwner*(owner: PSym)
|
||||
@@ -196,8 +196,8 @@ proc fillTypeS(dest: PType, kind: TTypeKind, c: PContext) =
|
||||
dest.owner = getCurrOwner()
|
||||
dest.size = - 1
|
||||
|
||||
proc makeRangeType(c: PContext, first, last: biggestInt,
|
||||
info: TLineInfo): PType =
|
||||
proc makeRangeType*(c: PContext, first, last: biggestInt,
|
||||
info: TLineInfo): PType =
|
||||
var n = newNodeI(nkRange, info)
|
||||
addSon(n, newIntNode(nkIntLit, first))
|
||||
addSon(n, newIntNode(nkIntLit, last))
|
||||
|
||||
@@ -222,11 +222,12 @@ proc semOf(c: PContext, n: PNode): PNode =
|
||||
|
||||
proc semIs(c: PContext, n: PNode): PNode =
|
||||
if sonsLen(n) == 3:
|
||||
var a = semExprWithType(c, n.sons[1], {efAllowType})
|
||||
var b = semExprWithType(c, n.sons[2], {efAllowType})
|
||||
result = newIntNode(nkIntLit, ord(sameType(a.typ, b.typ)))
|
||||
result.typ = getSysType(tyBool)
|
||||
result.info = n.info
|
||||
var a = semTypeNode(c, n[1], nil)
|
||||
var b = semTypeNode(c, n[2], nil)
|
||||
n.typ = getSysType(tyBool)
|
||||
n.sons[1] = newNodeIT(nkType, n[1].info, a)
|
||||
n.sons[2] = newNodeIT(nkType, n[2].info, b)
|
||||
result = n
|
||||
else:
|
||||
GlobalError(n.info, errXExpectsTwoArguments, "is")
|
||||
|
||||
|
||||
@@ -436,7 +436,9 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||
result = newIntNodeT(sonsLen(a), n)
|
||||
else:
|
||||
result = magicCall(m, n)
|
||||
else:
|
||||
of mIs:
|
||||
result = newIntNodeT(ord(sameType(n[1].typ, n[2].typ)), n)
|
||||
else:
|
||||
result = magicCall(m, n)
|
||||
except EOverflow:
|
||||
LocalError(n.info, errOverOrUnderflow)
|
||||
|
||||
@@ -527,8 +527,10 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
|
||||
# like: mydata.seq
|
||||
addSon(s.typ, newTypeS(tyEmpty, c))
|
||||
s.ast = a
|
||||
inc c.InGenericContext
|
||||
var body = semTypeNode(c, a.sons[2], nil)
|
||||
if body != nil:
|
||||
dec c.InGenericContext
|
||||
if body != nil:
|
||||
body.sym = s
|
||||
body.size = -1 # could not be computed properly
|
||||
s.typ.sons[sonsLen(s.typ) - 1] = body
|
||||
|
||||
@@ -351,31 +351,41 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||
|
||||
proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||
father: PNode, rectype: PSym) =
|
||||
var
|
||||
length: int
|
||||
f: PSym # new field
|
||||
a, it, e, branch: PNode
|
||||
typ: PType
|
||||
if n == nil:
|
||||
return # BUGFIX: nil is possible
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkRecWhen:
|
||||
branch = nil # the branch to take
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
it = n.sons[i]
|
||||
of nkRecWhen:
|
||||
var branch: PNode = nil # the branch to take
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var it = n.sons[i]
|
||||
if it == nil: illFormedAst(n)
|
||||
var idx = 1
|
||||
case it.kind
|
||||
of nkElifBranch:
|
||||
of nkElifBranch:
|
||||
checkSonsLen(it, 2)
|
||||
e = semConstBoolExpr(c, it.sons[0])
|
||||
if (e.kind != nkIntLit): InternalError(e.info, "semRecordNodeAux")
|
||||
if (e.intVal != 0) and (branch == nil): branch = it.sons[1]
|
||||
of nkElse:
|
||||
if c.InGenericContext == 0:
|
||||
var e = semConstBoolExpr(c, it.sons[0])
|
||||
if e.kind != nkIntLit: InternalError(e.info, "semRecordNodeAux")
|
||||
if e.intVal != 0 and branch == nil: branch = it.sons[1]
|
||||
else:
|
||||
it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0]))
|
||||
of nkElse:
|
||||
checkSonsLen(it, 1)
|
||||
if branch == nil: branch = it.sons[0]
|
||||
idx = 0
|
||||
else: illFormedAst(n)
|
||||
if branch != nil: semRecordNodeAux(c, branch, check, pos, father, rectype)
|
||||
of nkRecCase:
|
||||
if c.InGenericContext > 0:
|
||||
# use a new check intset here for each branch:
|
||||
var newCheck: TIntSet
|
||||
assign(newCheck, check)
|
||||
var newPos = pos
|
||||
var newf = newNodeI(nkRecList, n.info)
|
||||
semRecordNodeAux(c, it.sons[idx], newcheck, newpos, newf, rectype)
|
||||
it.sons[idx] = if newf.len == 1: newf[0] else: newf
|
||||
if c.InGenericContext > 0:
|
||||
addSon(father, n)
|
||||
elif branch != nil:
|
||||
semRecordNodeAux(c, branch, check, pos, father, rectype)
|
||||
of nkRecCase:
|
||||
semRecordCase(c, n, check, pos, father, rectype)
|
||||
of nkNilLit:
|
||||
if father.kind != nkRecList: addSon(father, newNodeI(nkRecList, n.info))
|
||||
@@ -385,20 +395,19 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
semRecordNodeAux(c, n.sons[i], check, pos, a, rectype)
|
||||
if a != father: addSon(father, a)
|
||||
of nkIdentDefs:
|
||||
of nkIdentDefs:
|
||||
checkMinSonsLen(n, 3)
|
||||
length = sonsLen(n)
|
||||
if (father.kind != nkRecList) and (length >= 4):
|
||||
a = newNodeI(nkRecList, n.info)
|
||||
else:
|
||||
a = ast.emptyNode
|
||||
if n.sons[length - 1].kind != nkEmpty:
|
||||
localError(n.sons[length - 1].info, errInitHereNotAllowed)
|
||||
if n.sons[length - 2].kind == nkEmpty:
|
||||
var length = sonsLen(n)
|
||||
var a: PNode
|
||||
if father.kind != nkRecList and length >= 4: a = newNodeI(nkRecList, n.info)
|
||||
else: a = ast.emptyNode
|
||||
if n.sons[length-1].kind != nkEmpty:
|
||||
localError(n.sons[length-1].info, errInitHereNotAllowed)
|
||||
if n.sons[length-2].kind == nkEmpty:
|
||||
GlobalError(n.info, errTypeExpected)
|
||||
typ = semTypeNode(c, n.sons[length-2], nil)
|
||||
for i in countup(0, sonsLen(n) - 3):
|
||||
f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
|
||||
var typ = semTypeNode(c, n.sons[length-2], nil)
|
||||
for i in countup(0, sonsLen(n)-3):
|
||||
var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
|
||||
f.typ = typ
|
||||
f.position = pos
|
||||
if (rectype != nil) and ({sfImportc, sfExportc} * rectype.flags != {}) and
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
# This module does the instantiation of generic types.
|
||||
|
||||
import ast, astalgo, msgs, types, semdata
|
||||
import ast, astalgo, msgs, types, semdata, renderer
|
||||
|
||||
proc checkPartialConstructedType(info: TLineInfo, t: PType) =
|
||||
if tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject:
|
||||
@@ -63,21 +63,51 @@ type
|
||||
|
||||
proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType
|
||||
proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym
|
||||
proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
|
||||
if n != nil:
|
||||
result = copyNode(n)
|
||||
result.typ = ReplaceTypeVarsT(cl, n.typ)
|
||||
case n.kind
|
||||
of nkNone..pred(nkSym), succ(nkSym)..nkNilLit:
|
||||
nil
|
||||
of nkSym:
|
||||
result.sym = ReplaceTypeVarsS(cl, n.sym)
|
||||
else:
|
||||
var length = sonsLen(n)
|
||||
if length > 0:
|
||||
newSons(result, length)
|
||||
for i in countup(0, length - 1):
|
||||
result.sons[i] = ReplaceTypeVarsN(cl, n.sons[i])
|
||||
|
||||
proc prepareNode(cl: var TReplTypeVars, n: PNode): PNode =
|
||||
result = copyNode(n)
|
||||
result.typ = ReplaceTypeVarsT(cl, n.typ)
|
||||
for i in 0 .. safeLen(n)-1:
|
||||
# XXX HACK: ``f(a, b)``, avoid to instantiate `f`
|
||||
if i == 0: result.add(n[i])
|
||||
else: result.add(prepareNode(cl, n[i]))
|
||||
|
||||
proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
|
||||
if n == nil: return
|
||||
result = copyNode(n)
|
||||
result.typ = ReplaceTypeVarsT(cl, n.typ)
|
||||
case n.kind
|
||||
of nkNone..pred(nkSym), succ(nkSym)..nkNilLit:
|
||||
nil
|
||||
of nkSym:
|
||||
result.sym = ReplaceTypeVarsS(cl, n.sym)
|
||||
of nkRecWhen:
|
||||
var branch: PNode = nil # the branch to take
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var it = n.sons[i]
|
||||
if it == nil: illFormedAst(n)
|
||||
case it.kind
|
||||
of nkElifBranch:
|
||||
checkSonsLen(it, 2)
|
||||
var cond = prepareNode(cl, it.sons[0])
|
||||
var e = cl.c.semConstExpr(cl.c, cond)
|
||||
if e.kind != nkIntLit:
|
||||
InternalError(e.info, "ReplaceTypeVarsN: when condition not a bool")
|
||||
if e.intVal != 0 and branch == nil: branch = it.sons[1]
|
||||
of nkElse:
|
||||
checkSonsLen(it, 1)
|
||||
if branch == nil: branch = it.sons[0]
|
||||
else: illFormedAst(n)
|
||||
if branch != nil:
|
||||
result = ReplaceTypeVarsN(cl, branch)
|
||||
else:
|
||||
result = newNodeI(nkRecList, n.info)
|
||||
else:
|
||||
var length = sonsLen(n)
|
||||
if length > 0:
|
||||
newSons(result, length)
|
||||
for i in countup(0, length - 1):
|
||||
result.sons[i] = ReplaceTypeVarsN(cl, n.sons[i])
|
||||
|
||||
proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
|
||||
if s == nil: return nil
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
## sparse bit set.
|
||||
## **Note**: Since Nimrod currently does not allow the assignment operator to
|
||||
## be overloaded, ``=`` for int sets performs some rather meaningless shallow
|
||||
## copy.
|
||||
## copy; use ``assign`` to get a deep copy.
|
||||
|
||||
import
|
||||
os, hashes, math
|
||||
@@ -137,6 +137,30 @@ proc initIntSet*: TIntSet =
|
||||
result.counter = 0
|
||||
result.head = nil
|
||||
|
||||
proc assign*(dest: var TIntSet, src: TIntSet) =
|
||||
## copies `src` to `dest`. `dest` does not need to be initialized by
|
||||
## `initIntSet`.
|
||||
dest.counter = src.counter
|
||||
dest.max = src.max
|
||||
newSeq(dest.data, src.data.len)
|
||||
|
||||
var it = src.head
|
||||
while it != nil:
|
||||
|
||||
var h = it.key and dest.max
|
||||
while dest.data[h] != nil: h = nextTry(h, dest.max)
|
||||
assert(dest.data[h] == nil)
|
||||
|
||||
var n: PTrunk
|
||||
new(n)
|
||||
n.next = dest.head
|
||||
n.key = it.key
|
||||
n.bits = it.bits
|
||||
dest.head = n
|
||||
dest.data[h] = n
|
||||
|
||||
it = it.next
|
||||
|
||||
template dollarImpl(): stmt =
|
||||
result = "{"
|
||||
for key in items(s):
|
||||
@@ -174,4 +198,7 @@ when isMainModule:
|
||||
x.incl(1056)
|
||||
for e in items(x): echo e
|
||||
|
||||
var y: TIntSet
|
||||
assign(y, x)
|
||||
for e in items(y): echo e
|
||||
|
||||
|
||||
@@ -224,7 +224,7 @@ proc setStyle*(style: set[TStyle]) =
|
||||
if styleBlink in style: a = a or int16(BACKGROUND_INTENSITY)
|
||||
if styleReverse in style: a = a or 0x4000'i16 # COMMON_LVB_REVERSE_VIDEO
|
||||
if styleUnderscore in style: a = a or 0x8000'i16 # COMMON_LVB_UNDERSCORE
|
||||
discard SetConsoleTextAttribute(conHandle, old or a)
|
||||
discard SetConsoleTextAttribute(conHandle, a)
|
||||
else:
|
||||
for s in items(style):
|
||||
stdout.write("\e[" & $ord(s) & 'm')
|
||||
|
||||
@@ -14,7 +14,7 @@ proc horrible() {.thread.} =
|
||||
var mydata = (x, "my string too")
|
||||
echo global
|
||||
|
||||
createThread(t, horrible)
|
||||
createThread[void](t, horrible)
|
||||
joinThread(t)
|
||||
|
||||
|
||||
|
||||
6
todo.txt
6
todo.txt
@@ -3,6 +3,7 @@ Version 0.8.14
|
||||
|
||||
- optimize unused constants away (affected by HLO)
|
||||
- fix thread tests
|
||||
- error message for imported procs in compiletime mode
|
||||
|
||||
version 0.9.0
|
||||
=============
|
||||
@@ -113,7 +114,10 @@ Low priority
|
||||
- resizing of strings/sequences could take into account the memory that
|
||||
is allocated
|
||||
- timeout for locks
|
||||
- adapt thread var emulation to care about the new merge operation
|
||||
- compilation cache:
|
||||
- adapt thread var emulation to care about the new merge operation
|
||||
- check for interface changes; if only the implemenation changes, no
|
||||
need to recompile clients
|
||||
- codegen should use "NIM_CAST" macro and respect aliasing rules for GCC
|
||||
|
||||
|
||||
|
||||
@@ -120,6 +120,7 @@ Library Additions
|
||||
- The ``osproc`` module now uses ``posix_spawn`` instead of ``fork``
|
||||
and ``exec`` on Posix systems. Define the symbol ``useFork`` to revert to
|
||||
the old implementation.
|
||||
- Added ``intsets.assign``.
|
||||
|
||||
|
||||
2011-07-10 Version 0.8.12 released
|
||||
|
||||
Reference in New Issue
Block a user