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
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 = proc getStrOrChar*(a: PNode): string =
case a.kind case a.kind
of nkStrLit..nkTripleStrLit: result = a.strVal of nkStrLit..nkTripleStrLit: result = a.strVal
of nkCharLit: result = chr(int(a.intVal)) & "" of nkCharLit: result = $chr(int(a.intVal))
else: else:
internalError(a.info, "getStrOrChar") internalError(a.info, "getStrOrChar")
result = "" result = ""

View file

@ -747,7 +747,7 @@ proc evalConStrStr(c: PEvalContext, n: PNode): PNode =
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
result = evalAux(c, n.sons[i], {}) result = evalAux(c, n.sons[i], {})
if isSpecial(result): return if isSpecial(result): return
a.strVal.add(getStrValue(result)) a.strVal.add(getStrOrChar(result))
result = a result = a
proc evalAppendStrStr(c: PEvalContext, n: PNode): PNode = proc evalAppendStrStr(c: PEvalContext, n: PNode): PNode =
@ -758,7 +758,7 @@ proc evalAppendStrStr(c: PEvalContext, n: PNode): PNode =
if isSpecial(result): return if isSpecial(result): return
var b = result var b = result
case a.kind 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") else: InternalError(n.info, "evalAppendStrStr")
result = emptyNode result = emptyNode

View file

@ -49,25 +49,26 @@ type
PGenericsCache* = ref TGenericsCache PGenericsCache* = ref TGenericsCache
PContext* = ref TContext PContext* = ref TContext
TContext* = object of TPassContext # a context represents a module TContext* = object of TPassContext # a context represents a module
module*: PSym # the module sym belonging to the context module*: PSym # the module sym belonging to the context
p*: PProcCon # procedure context p*: PProcCon # procedure context
generics*: PGenericsCache # may point to a global or module-local structure generics*: PGenericsCache # may point to a global or module-local structure
friendModule*: PSym # current friend module; may access private data; friendModule*: PSym # current friend module; may access private data;
# this is used so that generic instantiations can # this is used so that generic instantiations
# access private object fields # can access private object fields
InstCounter*: int # to prevent endless instantiations InstCounter*: int # to prevent endless instantiations
threadEntries*: TSymSeq # list of thread entries to check threadEntries*: TSymSeq # list of thread entries to check
tab*: TSymTab # each module has its own symbol table tab*: TSymTab # each module has its own symbol table
AmbiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot AmbiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot
# store this info in the syms themselves!) # 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 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 semConstExpr*: proc (c: PContext, n: PNode): PNode # for the pragmas
semExpr*: 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 includedFiles*: TIntSet # used to detect recursive include files
filename*: string # the module's filename filename*: string # the module's filename
userPragmas*: TStrTable userPragmas*: TStrTable
evalContext*: PEvalContext evalContext*: PEvalContext
slurpedFiles*: seq[string] slurpedFiles*: seq[string]
@ -91,8 +92,7 @@ proc makePtrType*(c: PContext, baseType: PType): PType
proc makeVarType*(c: PContext, baseType: PType): PType proc makeVarType*(c: PContext, baseType: PType): PType
proc newTypeS*(kind: TTypeKind, c: PContext): PType proc newTypeS*(kind: TTypeKind, c: PContext): PType
proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext) proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext)
proc makeRangeType*(c: PContext, first, last: biggestInt, info: TLineInfo): PType
# owner handling: # owner handling:
proc getCurrOwner*(): PSym proc getCurrOwner*(): PSym
proc PushOwner*(owner: PSym) proc PushOwner*(owner: PSym)
@ -196,8 +196,8 @@ proc fillTypeS(dest: PType, kind: TTypeKind, c: PContext) =
dest.owner = getCurrOwner() dest.owner = getCurrOwner()
dest.size = - 1 dest.size = - 1
proc makeRangeType(c: PContext, first, last: biggestInt, proc makeRangeType*(c: PContext, first, last: biggestInt,
info: TLineInfo): PType = info: TLineInfo): PType =
var n = newNodeI(nkRange, info) var n = newNodeI(nkRange, info)
addSon(n, newIntNode(nkIntLit, first)) addSon(n, newIntNode(nkIntLit, first))
addSon(n, newIntNode(nkIntLit, last)) 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 = proc semIs(c: PContext, n: PNode): PNode =
if sonsLen(n) == 3: if sonsLen(n) == 3:
var a = semExprWithType(c, n.sons[1], {efAllowType}) var a = semTypeNode(c, n[1], nil)
var b = semExprWithType(c, n.sons[2], {efAllowType}) var b = semTypeNode(c, n[2], nil)
result = newIntNode(nkIntLit, ord(sameType(a.typ, b.typ))) n.typ = getSysType(tyBool)
result.typ = getSysType(tyBool) n.sons[1] = newNodeIT(nkType, n[1].info, a)
result.info = n.info n.sons[2] = newNodeIT(nkType, n[2].info, b)
result = n
else: else:
GlobalError(n.info, errXExpectsTwoArguments, "is") GlobalError(n.info, errXExpectsTwoArguments, "is")

View file

@ -436,7 +436,9 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
result = newIntNodeT(sonsLen(a), n) result = newIntNodeT(sonsLen(a), n)
else: else:
result = magicCall(m, n) result = magicCall(m, n)
else: of mIs:
result = newIntNodeT(ord(sameType(n[1].typ, n[2].typ)), n)
else:
result = magicCall(m, n) result = magicCall(m, n)
except EOverflow: except EOverflow:
LocalError(n.info, errOverOrUnderflow) LocalError(n.info, errOverOrUnderflow)

View file

@ -527,8 +527,10 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
# like: mydata.seq # like: mydata.seq
addSon(s.typ, newTypeS(tyEmpty, c)) addSon(s.typ, newTypeS(tyEmpty, c))
s.ast = a s.ast = a
inc c.InGenericContext
var body = semTypeNode(c, a.sons[2], nil) var body = semTypeNode(c, a.sons[2], nil)
if body != nil: dec c.InGenericContext
if body != nil:
body.sym = s body.sym = s
body.size = -1 # could not be computed properly body.size = -1 # could not be computed properly
s.typ.sons[sonsLen(s.typ) - 1] = body 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, proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
father: PNode, rectype: PSym) = father: PNode, rectype: PSym) =
var if n == nil: return
length: int
f: PSym # new field
a, it, e, branch: PNode
typ: PType
if n == nil:
return # BUGFIX: nil is possible
case n.kind case n.kind
of nkRecWhen: of nkRecWhen:
branch = nil # the branch to take var branch: PNode = nil # the branch to take
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
it = n.sons[i] var it = n.sons[i]
if it == nil: illFormedAst(n) if it == nil: illFormedAst(n)
var idx = 1
case it.kind case it.kind
of nkElifBranch: of nkElifBranch:
checkSonsLen(it, 2) checkSonsLen(it, 2)
e = semConstBoolExpr(c, it.sons[0]) if c.InGenericContext == 0:
if (e.kind != nkIntLit): InternalError(e.info, "semRecordNodeAux") var e = semConstBoolExpr(c, it.sons[0])
if (e.intVal != 0) and (branch == nil): branch = it.sons[1] if e.kind != nkIntLit: InternalError(e.info, "semRecordNodeAux")
of nkElse: 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) checkSonsLen(it, 1)
if branch == nil: branch = it.sons[0] if branch == nil: branch = it.sons[0]
idx = 0
else: illFormedAst(n) else: illFormedAst(n)
if branch != nil: semRecordNodeAux(c, branch, check, pos, father, rectype) if c.InGenericContext > 0:
of nkRecCase: # 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) semRecordCase(c, n, check, pos, father, rectype)
of nkNilLit: of nkNilLit:
if father.kind != nkRecList: addSon(father, newNodeI(nkRecList, n.info)) 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): for i in countup(0, sonsLen(n) - 1):
semRecordNodeAux(c, n.sons[i], check, pos, a, rectype) semRecordNodeAux(c, n.sons[i], check, pos, a, rectype)
if a != father: addSon(father, a) if a != father: addSon(father, a)
of nkIdentDefs: of nkIdentDefs:
checkMinSonsLen(n, 3) checkMinSonsLen(n, 3)
length = sonsLen(n) var length = sonsLen(n)
if (father.kind != nkRecList) and (length >= 4): var a: PNode
a = newNodeI(nkRecList, n.info) if father.kind != nkRecList and length >= 4: a = newNodeI(nkRecList, n.info)
else: else: a = ast.emptyNode
a = ast.emptyNode if n.sons[length-1].kind != nkEmpty:
if n.sons[length - 1].kind != nkEmpty: localError(n.sons[length-1].info, errInitHereNotAllowed)
localError(n.sons[length - 1].info, errInitHereNotAllowed) if n.sons[length-2].kind == nkEmpty:
if n.sons[length - 2].kind == nkEmpty:
GlobalError(n.info, errTypeExpected) GlobalError(n.info, errTypeExpected)
typ = semTypeNode(c, n.sons[length-2], nil) var typ = semTypeNode(c, n.sons[length-2], nil)
for i in countup(0, sonsLen(n) - 3): for i in countup(0, sonsLen(n)-3):
f = semIdentWithPragma(c, skField, n.sons[i], {sfExported}) var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
f.typ = typ f.typ = typ
f.position = pos f.position = pos
if (rectype != nil) and ({sfImportc, sfExportc} * rectype.flags != {}) and if (rectype != nil) and ({sfImportc, sfExportc} * rectype.flags != {}) and

View file

@ -9,7 +9,7 @@
# This module does the instantiation of generic types. # 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) = proc checkPartialConstructedType(info: TLineInfo, t: PType) =
if tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject: 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 ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType
proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym
proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
if n != nil: proc prepareNode(cl: var TReplTypeVars, n: PNode): PNode =
result = copyNode(n) result = copyNode(n)
result.typ = ReplaceTypeVarsT(cl, n.typ) result.typ = ReplaceTypeVarsT(cl, n.typ)
case n.kind for i in 0 .. safeLen(n)-1:
of nkNone..pred(nkSym), succ(nkSym)..nkNilLit: # XXX HACK: ``f(a, b)``, avoid to instantiate `f`
nil if i == 0: result.add(n[i])
of nkSym: else: result.add(prepareNode(cl, n[i]))
result.sym = ReplaceTypeVarsS(cl, n.sym)
else: proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
var length = sonsLen(n) if n == nil: return
if length > 0: result = copyNode(n)
newSons(result, length) result.typ = ReplaceTypeVarsT(cl, n.typ)
for i in countup(0, length - 1): case n.kind
result.sons[i] = ReplaceTypeVarsN(cl, n.sons[i]) 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 = proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
if s == nil: return nil if s == nil: return nil

View file

@ -11,7 +11,7 @@
## sparse bit set. ## sparse bit set.
## **Note**: Since Nimrod currently does not allow the assignment operator to ## **Note**: Since Nimrod currently does not allow the assignment operator to
## be overloaded, ``=`` for int sets performs some rather meaningless shallow ## be overloaded, ``=`` for int sets performs some rather meaningless shallow
## copy. ## copy; use ``assign`` to get a deep copy.
import import
os, hashes, math os, hashes, math
@ -137,6 +137,30 @@ proc initIntSet*: TIntSet =
result.counter = 0 result.counter = 0
result.head = nil 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 = template dollarImpl(): stmt =
result = "{" result = "{"
for key in items(s): for key in items(s):
@ -174,4 +198,7 @@ when isMainModule:
x.incl(1056) x.incl(1056)
for e in items(x): echo e 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 styleBlink in style: a = a or int16(BACKGROUND_INTENSITY)
if styleReverse in style: a = a or 0x4000'i16 # COMMON_LVB_REVERSE_VIDEO 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 if styleUnderscore in style: a = a or 0x8000'i16 # COMMON_LVB_UNDERSCORE
discard SetConsoleTextAttribute(conHandle, old or a) discard SetConsoleTextAttribute(conHandle, a)
else: else:
for s in items(style): for s in items(style):
stdout.write("\e[" & $ord(s) & 'm') stdout.write("\e[" & $ord(s) & 'm')

View file

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

View file

@ -3,6 +3,7 @@ Version 0.8.14
- optimize unused constants away (affected by HLO) - optimize unused constants away (affected by HLO)
- fix thread tests - fix thread tests
- error message for imported procs in compiletime mode
version 0.9.0 version 0.9.0
============= =============
@ -113,7 +114,10 @@ Low priority
- resizing of strings/sequences could take into account the memory that - resizing of strings/sequences could take into account the memory that
is allocated is allocated
- timeout for locks - 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 - 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`` - The ``osproc`` module now uses ``posix_spawn`` instead of ``fork``
and ``exec`` on Posix systems. Define the symbol ``useFork`` to revert to and ``exec`` on Posix systems. Define the symbol ``useFork`` to revert to
the old implementation. the old implementation.
- Added ``intsets.assign``.
2011-07-10 Version 0.8.12 released 2011-07-10 Version 0.8.12 released