diff options
-rwxr-xr-x | compiler/ast.nim | 2 | ||||
-rwxr-xr-x | compiler/evals.nim | 4 | ||||
-rwxr-xr-x | compiler/semdata.nim | 34 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 11 | ||||
-rwxr-xr-x | compiler/semfold.nim | 4 | ||||
-rwxr-xr-x | compiler/semstmts.nim | 4 | ||||
-rwxr-xr-x | compiler/semtypes.nim | 69 | ||||
-rwxr-xr-x | compiler/semtypinst.nim | 62 | ||||
-rwxr-xr-x | lib/pure/collections/intsets.nim | 29 | ||||
-rwxr-xr-x | lib/pure/terminal.nim | 2 | ||||
-rwxr-xr-x | tests/threads/tthreadheapviolation1.nim | 2 | ||||
-rwxr-xr-x | todo.txt | 6 | ||||
-rwxr-xr-x | web/news.txt | 1 |
13 files changed, 153 insertions, 77 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 7f28d7b89..3fdf5f6e3 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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 = "" diff --git a/compiler/evals.nim b/compiler/evals.nim index cc05267f4..9f677b705 100755 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -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 diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 39e4892b2..1037d2914 100755 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -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)) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index af3048586..d21f557d4 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -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") diff --git a/compiler/semfold.nim b/compiler/semfold.nim index f317340da..afa1090a7 100755 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -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) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 8412d4783..2818ecbd1 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -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 diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index e51e02f2d..ca7988aeb 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -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 diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 0473f2f74..55bf2dcc8 100755 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -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 diff --git a/lib/pure/collections/intsets.nim b/lib/pure/collections/intsets.nim index 3fd81acf6..6164593c1 100755 --- a/lib/pure/collections/intsets.nim +++ b/lib/pure/collections/intsets.nim @@ -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 diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim index 0fd631eed..20eaa4d36 100755 --- a/lib/pure/terminal.nim +++ b/lib/pure/terminal.nim @@ -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') diff --git a/tests/threads/tthreadheapviolation1.nim b/tests/threads/tthreadheapviolation1.nim index cd35a44ca..7ca6f7928 100755 --- a/tests/threads/tthreadheapviolation1.nim +++ b/tests/threads/tthreadheapviolation1.nim @@ -14,7 +14,7 @@ proc horrible() {.thread.} = var mydata = (x, "my string too") echo global -createThread(t, horrible) +createThread[void](t, horrible) joinThread(t) diff --git a/todo.txt b/todo.txt index f0620de1a..50824ace1 100755 --- a/todo.txt +++ b/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 diff --git a/web/news.txt b/web/news.txt index 29d0df8b9..3ad135ec8 100755 --- a/web/news.txt +++ b/web/news.txt @@ -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 |