bugfix: 'when' sections in generic objects now work, so TThread[void] compiles

This commit is contained in:
Araq
2011-11-20 16:13:03 +01:00
parent a274f3bf5b
commit 72651de710
13 changed files with 153 additions and 77 deletions

View File

@@ -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 = ""

View File

@@ -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

View File

@@ -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))

View File

@@ -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")

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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')

View File

@@ -14,7 +14,7 @@ proc horrible() {.thread.} =
var mydata = (x, "my string too")
echo global
createThread(t, horrible)
createThread[void](t, horrible)
joinThread(t)

View File

@@ -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

View File

@@ -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