bugfix: 'when' sections in generic objects now work, so TThread[void] compiles
This commit is contained in:
parent
a274f3bf5b
commit
72651de710
13 changed files with 153 additions and 77 deletions
|
|
@ -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 = ""
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,14 +53,15 @@ type
|
||||||
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!)
|
||||||
|
InGenericContext*: int # > 0 if we are in a generic
|
||||||
converters*: TSymSeq # sequence of converters
|
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
|
||||||
|
|
@ -91,7 +92,6 @@ 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
|
||||||
|
|
@ -196,7 +196,7 @@ 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))
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -436,6 +436,8 @@ 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)
|
||||||
|
of mIs:
|
||||||
|
result = newIntNodeT(ord(sameType(n[1].typ, n[2].typ)), n)
|
||||||
else:
|
else:
|
||||||
result = magicCall(m, n)
|
result = magicCall(m, n)
|
||||||
except EOverflow:
|
except EOverflow:
|
||||||
|
|
|
||||||
|
|
@ -527,7 +527,9 @@ 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)
|
||||||
|
dec c.InGenericContext
|
||||||
if body != nil:
|
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
|
||||||
|
|
|
||||||
|
|
@ -351,30 +351,40 @@ 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")
|
||||||
|
if e.intVal != 0 and branch == nil: branch = it.sons[1]
|
||||||
|
else:
|
||||||
|
it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0]))
|
||||||
of nkElse:
|
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:
|
||||||
|
# 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:
|
of nkRecCase:
|
||||||
semRecordCase(c, n, check, pos, father, rectype)
|
semRecordCase(c, n, check, pos, father, rectype)
|
||||||
of nkNilLit:
|
of nkNilLit:
|
||||||
|
|
@ -387,18 +397,17 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -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,8 +63,17 @@ 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 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 =
|
proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
|
||||||
if n != nil:
|
if n == nil: return
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
result.typ = ReplaceTypeVarsT(cl, n.typ)
|
result.typ = ReplaceTypeVarsT(cl, n.typ)
|
||||||
case n.kind
|
case n.kind
|
||||||
|
|
@ -72,6 +81,27 @@ proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
|
||||||
nil
|
nil
|
||||||
of nkSym:
|
of nkSym:
|
||||||
result.sym = ReplaceTypeVarsS(cl, n.sym)
|
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:
|
else:
|
||||||
var length = sonsLen(n)
|
var length = sonsLen(n)
|
||||||
if length > 0:
|
if length > 0:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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')
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
4
todo.txt
4
todo.txt
|
|
@ -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
|
||||||
|
- compilation cache:
|
||||||
- adapt thread var emulation to care about the new merge operation
|
- 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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue