diff options
author | Araq <rumpf_a@web.de> | 2011-11-20 16:13:03 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-11-20 16:13:03 +0100 |
commit | 72651de7103a85f68b6e86353960daf6e62b37df (patch) | |
tree | 7ec632d331ab39149fef59d8bcee66247a6556c7 /compiler | |
parent | a274f3bf5be3fc35f1538e5aab0e32fb9ed2ff82 (diff) | |
download | Nim-72651de7103a85f68b6e86353960daf6e62b37df.tar.gz |
bugfix: 'when' sections in generic objects now work, so TThread[void] compiles
Diffstat (limited to 'compiler')
-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 |
8 files changed, 117 insertions, 73 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 |