diff options
-rw-r--r-- | compiler/ccgcalls.nim | 15 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 23 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 114 | ||||
-rw-r--r-- | compiler/ccgutils.nim | 6 | ||||
-rw-r--r-- | compiler/cgen.nim | 4 | ||||
-rw-r--r-- | compiler/msgs.nim | 7 | ||||
-rw-r--r-- | compiler/sem.nim | 10 | ||||
-rw-r--r-- | compiler/semexprs.nim | 6 | ||||
-rw-r--r-- | compiler/semstmts.nim | 13 | ||||
-rw-r--r-- | compiler/types.nim | 101 | ||||
-rw-r--r-- | koch.nim | 6 | ||||
-rw-r--r-- | lib/pure/httpclient.nim | 49 | ||||
-rw-r--r-- | lib/pure/selectors.nim | 2 | ||||
-rw-r--r-- | lib/pure/terminal.nim | 8 | ||||
-rw-r--r-- | lib/system.nim | 2 | ||||
-rw-r--r-- | lib/system/excpt.nim | 2 | ||||
-rw-r--r-- | tests/generics/tgeneric_inheritance.nim | 2 | ||||
-rw-r--r-- | tests/generics/tmetafield.nim | 2 | ||||
-rw-r--r-- | web/community.txt | 10 |
19 files changed, 225 insertions, 157 deletions
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 4f7856769..cb8dcc25b 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -302,10 +302,11 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): PRope = while i < pat.len: case pat[i] of '@': - result.app genOtherArg(p, ri, j, typ) - for k in j+1 .. < ri.len: - result.app(~", ") - result.app genOtherArg(p, ri, k, typ) + if j < ri.len: + result.app genOtherArg(p, ri, j, typ) + for k in j+1 .. < ri.len: + result.app(~", ") + result.app genOtherArg(p, ri, k, typ) inc i of '#': if pat[i+1] in {'+', '@'}: @@ -448,8 +449,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) = proc genCall(p: BProc, e: PNode, d: var TLoc) = if e.sons[0].typ.callConv == ccClosure: genClosureCall(p, nil, e, d) - elif e.sons[0].kind == nkSym and sfInfixCall in e.sons[0].sym.flags and - e.len >= 2: + elif e.sons[0].kind == nkSym and sfInfixCall in e.sons[0].sym.flags: genInfixCall(p, nil, e, d) elif e.sons[0].kind == nkSym and sfNamedParamCall in e.sons[0].sym.flags: genNamedParamCall(p, e, d) @@ -462,8 +462,7 @@ proc genCall(p: BProc, e: PNode, d: var TLoc) = proc genAsgnCall(p: BProc, le, ri: PNode, d: var TLoc) = if ri.sons[0].typ.callConv == ccClosure: genClosureCall(p, le, ri, d) - elif ri.sons[0].kind == nkSym and sfInfixCall in ri.sons[0].sym.flags and - ri.len >= 2: + elif ri.sons[0].kind == nkSym and sfInfixCall in ri.sons[0].sym.flags: genInfixCall(p, le, ri, d) elif ri.sons[0].kind == nkSym and sfNamedParamCall in ri.sons[0].sym.flags: genNamedParamCall(p, ri, d) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 90aefd7d6..98fb25899 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -229,8 +229,9 @@ proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = flags - {needToCopy} else: flags - for i in 0 .. <dest.t.len: - let t = dest.t.sons[i] + let t = skipTypes(dest.t, abstractInst) + for i in 0 .. <t.len: + let t = t.sons[i] let field = ropef("Field$1", i.toRope) genAssignment(p, optAsgnLoc(dest, t, field), optAsgnLoc(src, t, field), newflags) @@ -328,7 +329,9 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) of tyObject: # XXX: check for subtyping? - if not isObjLackingTypeField(ty): + if ty.isImportedCppType: + linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) + elif not isObjLackingTypeField(ty): genGenericAsgn(p, dest, src, flags) elif needsComplexAssignment(ty): if ty.sons[0].isNil and asgnComplexity(ty.n) <= 4: @@ -411,7 +414,7 @@ proc putDataIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) = var a: TLoc if d.k != locNone: # need to generate an assignment here - initLoc(a, locData, getUniqueType(t), OnUnknown) + initLoc(a, locData, t, OnUnknown) a.r = r if lfNoDeepCopy in d.flags: genAssignment(p, d, a, {}) else: genAssignment(p, d, a, {needToCopy}) @@ -419,14 +422,14 @@ proc putDataIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) = # we cannot call initLoc() here as that would overwrite # the flags field! d.k = locData - d.t = getUniqueType(t) + d.t = t d.r = r proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) = var a: TLoc if d.k != locNone: # need to generate an assignment here - initLoc(a, locExpr, getUniqueType(t), OnUnknown) + initLoc(a, locExpr, t, OnUnknown) a.r = r if lfNoDeepCopy in d.flags: genAssignment(p, d, a, {}) else: genAssignment(p, d, a, {needToCopy}) @@ -434,7 +437,7 @@ proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) = # we cannot call initLoc() here as that would overwrite # the flags field! d.k = locExpr - d.t = getUniqueType(t) + d.t = t d.r = r proc binaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) = @@ -684,7 +687,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) = # so the '&' and '*' cancel out: putIntoDest(p, d, a.t.sons[0], rdLoc(a)) else: - putIntoDest(p, d, a.t.sons[0], ropef("(*$1)", [rdLoc(a)])) + putIntoDest(p, d, e.typ, ropef("(*$1)", [rdLoc(a)])) proc genAddr(p: BProc, e: PNode, d: var TLoc) = # careful 'addr(myptrToArray)' needs to get the ampersand: @@ -710,7 +713,7 @@ proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc): PType = if e.sons[1].kind != nkSym: internalError(e.info, "genRecordFieldAux") d.inheritLocation(a) discard getTypeDesc(p.module, a.t) # fill the record's fields.loc - result = a.t + result = a.t.getUniqueType proc genTupleElem(p: BProc, e: PNode, d: var TLoc) = var @@ -719,7 +722,7 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) = initLocExpr(p, e.sons[0], a) d.inheritLocation(a) discard getTypeDesc(p.module, a.t) # fill the record's fields.loc - var ty = a.t + var ty = a.t.getUniqueType var r = rdLoc(a) case e.sons[1].kind of nkIntLit..nkUInt64Lit: i = int(e.sons[1].intVal) diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 12dd2a8de..90996d9cd 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -199,7 +199,7 @@ const proc cacheGetType(tab: TIdTable, key: PType): PRope = # returns nil if we need to declare this type - # since types are now unique via the ``GetUniqueType`` mechanism, this slow + # since types are now unique via the ``getUniqueType`` mechanism, this slow # linear search is not necessary anymore: result = PRope(idTableGet(tab, key)) @@ -298,7 +298,10 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var PRope, params = con("(", params) proc isImportedType(t: PType): bool = - result = (t.sym != nil) and (sfImportc in t.sym.flags) + result = t.sym != nil and sfImportc in t.sym.flags + +proc isImportedCppType(t: PType): bool = + result = t.sym != nil and sfInfixCall in t.sym.flags proc typeNameOrLiteral(t: PType, literal: string): PRope = if (t.sym != nil) and (sfImportc in t.sym.flags) and (t.sym.magic == mNone): @@ -387,7 +390,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode, for i in countup(0, sonsLen(n) - 1): app(result, genRecordFieldsAux(m, n.sons[i], accessExpr, rectype, check)) of nkRecCase: - if (n.sons[0].kind != nkSym): internalError(n.info, "genRecordFieldsAux") + if n.sons[0].kind != nkSym: internalError(n.info, "genRecordFieldsAux") app(result, genRecordFieldsAux(m, n.sons[0], accessExpr, rectype, check)) uname = toRope(mangle(n.sons[0].sym.name.s) & 'U') if accessExpr != nil: ae = ropef("$1.$2", [accessExpr, uname]) @@ -418,12 +421,14 @@ proc genRecordFieldsAux(m: BModule, n: PNode, if accessExpr != nil: ae = ropef("$1.$2", [accessExpr, sname]) else: ae = sname fillLoc(field.loc, locField, field.typ, ae, OnUnknown) - let fieldType = field.loc.t + let fieldType = field.loc.t.skipTypes(abstractInst) if fieldType.kind == tyArray and tfUncheckedArray in fieldType.flags: appf(result, "$1 $2[SEQ_DECL_SIZE];$n", [getTypeDescAux(m, fieldType.elemType, check), sname]) else: - appf(result, "$1 $2;$n", [getTypeDescAux(m, fieldType, check), sname]) + # don't use fieldType here because we need the + # tyGenericInst for C++ template support + appf(result, "$1 $2;$n", [getTypeDescAux(m, field.loc.t, check), sname]) else: internalError(n.info, "genRecordFieldsAux()") proc getRecordFields(m: BModule, typ: PType, check: var IntSet): PRope = @@ -483,11 +488,7 @@ proc pushType(m: BModule, typ: PType) = proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = # returns only the type's name - var - name, rettype, desc, recdesc: PRope - n: BiggestInt - t, et: PType - t = getUniqueType(typ) + var t = getUniqueType(typ) if t == nil: internalError("getTypeDescAux: t == nil") if t.sym != nil: useHeader(m, t.sym) result = getTypePre(m, t) @@ -499,35 +500,42 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = # C type generation into an analysis and a code generation phase somehow. case t.kind of tyRef, tyPtr, tyVar: - et = getUniqueType(t.lastSon) - if et.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}: + var et = t.lastSon + var etB = et.skipTypes(abstractInst) + if etB.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}: # this is correct! sets have no proper base type, so we treat # ``var set[char]`` in `getParamTypeDesc` - et = getUniqueType(elemType(et)) - case et.kind - of tyObject, tyTuple: - # no restriction! We have a forward declaration for structs - name = getTypeForward(m, et) - result = con(name, "*") - idTablePut(m.typeCache, t, result) - pushType(m, et) - of tySequence: + et = elemType(etB) + etB = et.skipTypes(abstractInst) + case etB.kind + of tyObject, tyTuple: + if isImportedCppType(etB) and et.kind == tyGenericInst: + result = con(getTypeDescAux(m, et, check), "*") + else: + # no restriction! We have a forward declaration for structs + let x = getUniqueType(etB) + let name = getTypeForward(m, x) + result = con(name, "*") + idTablePut(m.typeCache, t, result) + pushType(m, x) + of tySequence: # no restriction! We have a forward declaration for structs - name = getTypeForward(m, et) + let x = getUniqueType(etB) + let name = getTypeForward(m, x) result = con(name, "**") idTablePut(m.typeCache, t, result) - pushType(m, et) - else: + pushType(m, x) + else: # else we have a strong dependency :-( result = con(getTypeDescAux(m, et, check), "*") idTablePut(m.typeCache, t, result) - of tyOpenArray, tyVarargs: - et = getUniqueType(t.sons[0]) - result = con(getTypeDescAux(m, et, check), "*") + of tyOpenArray, tyVarargs: + result = con(getTypeDescAux(m, t.sons[0], check), "*") idTablePut(m.typeCache, t, result) - of tyProc: + of tyProc: result = getTypeName(t) idTablePut(m.typeCache, t, result) + var rettype, desc: PRope genProcParams(m, t, rettype, desc, check) if not isImportedType(t): if t.callConv != ccClosure: # procedure vars may need a closure! @@ -542,7 +550,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = # we cannot use getTypeForward here because then t would be associated # with the name of the struct, not with the pointer to the struct: result = cacheGetType(m.forwTypeCache, t) - if result == nil: + if result == nil: result = getTypeName(t) if not isImportedType(t): appf(m.s[cfsForwardTypes], getForwardStructFormat(m), @@ -564,27 +572,39 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = result = toRope("TGenericSeq") app(result, "*") of tyArrayConstr, tyArray: - n = lengthOrd(t) - if n <= 0: - n = 1 # make an array of at least one element + var n: BiggestInt = lengthOrd(t) + if n <= 0: n = 1 # make an array of at least one element result = getTypeName(t) idTablePut(m.typeCache, t, result) - if not isImportedType(t): + if not isImportedType(t): + let foo = getTypeDescAux(m, t.sons[1], check) appf(m.s[cfsTypes], "typedef $1 $2[$3];$n", - [getTypeDescAux(m, t.sons[1], check), result, toRope(n)]) - of tyObject, tyTuple: - result = cacheGetType(m.forwTypeCache, t) - if result == nil: - result = getTypeName(t) - if not isImportedType(t): - appf(m.s[cfsForwardTypes], getForwardStructFormat(m), - [structOrUnion(t), result]) - idTablePut(m.forwTypeCache, t, result) - idTablePut(m.typeCache, t, result) # always call for sideeffects: - if t.kind != tyTuple: recdesc = getRecordDesc(m, t, result, check) - else: recdesc = getTupleDesc(m, t, result, check) - if not isImportedType(t): app(m.s[cfsTypes], recdesc) - of tySet: + [foo, result, toRope(n)]) + of tyObject, tyTuple: + if isImportedCppType(t) and typ.kind == tyGenericInst: + # for instantiated templates we do not go through the type cache as the + # the type cache is not aware of 'tyGenericInst'. + result = getTypeName(t).con("<") + for i in 1 .. typ.len-2: + if i > 1: result.app(", ") + result.app(getTypeDescAux(m, typ.sons[i], check)) + result.app("> ") + # always call for sideeffects: + assert t.kind != tyTuple + discard getRecordDesc(m, t, result, check) + else: + result = cacheGetType(m.forwTypeCache, t) + if result == nil: + result = getTypeName(t) + if not isImportedType(t): + appf(m.s[cfsForwardTypes], getForwardStructFormat(m), + [structOrUnion(t), result]) + idTablePut(m.forwTypeCache, t, result) + idTablePut(m.typeCache, t, result) # always call for sideeffects: + let recdesc = if t.kind != tyTuple: getRecordDesc(m, t, result, check) + else: getTupleDesc(m, t, result, check) + if not isImportedType(t): app(m.s[cfsTypes], recdesc) + of tySet: case int(getSize(t)) of 1: result = toRope("NU8") of 2: result = toRope("NU16") diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index 7396c0bf8..1e1fcd6fb 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -75,8 +75,7 @@ proc getUniqueType*(key: PType): PType = if key == nil: return var k = key.kind case k - of tyBool, tyChar, - tyInt..tyUInt64: + of tyBool, tyChar, tyInt..tyUInt64: # no canonicalization for integral types, so that e.g. ``pid_t`` is # produced instead of ``NI``. result = key @@ -86,8 +85,7 @@ proc getUniqueType*(key: PType): PType = if result == nil: gCanonicalTypes[k] = key result = key - of tyTypeDesc, tyTypeClasses, tyGenericParam, - tyFromExpr, tyFieldAccessor: + of tyTypeDesc, tyTypeClasses, tyGenericParam, tyFromExpr, tyFieldAccessor: internalError("GetUniqueType") of tyDistinct: if key.deepCopy != nil: result = key diff --git a/compiler/cgen.nim b/compiler/cgen.nim index f3fa6a63e..480c131ae 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -53,7 +53,7 @@ proc emitLazily(s: PSym): bool {.inline.} = proc initLoc(result: var TLoc, k: TLocKind, typ: PType, s: TStorageLoc) = result.k = k result.s = s - result.t = getUniqueType(typ) + result.t = typ result.r = nil result.flags = {} @@ -61,7 +61,7 @@ proc fillLoc(a: var TLoc, k: TLocKind, typ: PType, r: PRope, s: TStorageLoc) = # fills the loc if it is not already initialized if a.k == locNone: a.k = k - a.t = getUniqueType(typ) + a.t = typ a.s = s if a.r == nil: a.r = r diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 17b2c4606..d94b8ade8 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -120,7 +120,7 @@ type warnDifferentHeaps, warnWriteToForeignHeap, warnUnsafeCode, warnEachIdentIsTuple, warnShadowIdent, warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2, - warnUninit, warnGcMem, warnLockLevel, warnUser, + warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnUser, hintSuccess, hintSuccessX, hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded, hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled, @@ -392,6 +392,7 @@ const warnGcUnsafe2: "cannot prove '$1' is GC-safe. Does not compile with --threads:on.", warnUninit: "'$1' might not have been initialized [Uninit]", warnGcMem: "'$1' uses GC'ed memory [GcMem]", + warnDestructor: "usage of a type with a destructor in a non destructible context. This will become a compile time error in the future. [Destructor]", warnLockLevel: "$1 [LockLevel]", warnUser: "$1 [User]", hintSuccess: "operation successful [Success]", @@ -413,7 +414,7 @@ const hintUser: "$1 [User]"] const - WarningsToStr*: array[0..28, string] = ["CannotOpenFile", "OctalEscape", + WarningsToStr*: array[0..29, string] = ["CannotOpenFile", "OctalEscape", "XIsNeverRead", "XmightNotBeenInit", "Deprecated", "ConfigDeprecated", "SmallLshouldNotBeUsed", "UnknownMagic", @@ -423,7 +424,7 @@ const "AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap", "UnsafeCode", "EachIdentIsTuple", "ShadowIdent", "ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit", - "GcMem", "LockLevel", "User"] + "GcMem", "Destructor", "LockLevel", "User"] HintsToStr*: array[0..16, string] = ["Success", "SuccessX", "LineTooLong", "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", diff --git a/compiler/sem.nim b/compiler/sem.nim index 9ac7ad139..90037fccd 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -175,9 +175,15 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym proc semStmtScope(c: PContext, n: PNode): PNode +proc typeAllowedCheck(info: TLineInfo; typ: PType; kind: TSymKind) = + let t = typeAllowed(typ, kind) + if t != nil: + if t == typ: localError(info, "invalid type: '" & typeToString(typ) & "'") + else: localError(info, "invalid type: '" & typeToString(t) & + "' in this context: '" & typeToString(typ) & "'") + proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} = - if not typeAllowed(typ, skConst): - localError(typ.n.info, errXisNoType, typeToString(typ)) + typeAllowedCheck(typ.n.info, typ, skConst) proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 9d9a5a50c..8221ed372 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -214,9 +214,9 @@ proc isCastable(dst, src: PType): bool = result = false elif srcSize < 0: result = false - elif not typeAllowed(dst, skParam): + elif typeAllowed(dst, skParam) != nil: result = false - else: + else: result = (dstSize >= srcSize) or (skipTypes(dst, abstractInst).kind in IntegralTypes) or (skipTypes(src, abstractInst-{tyTypeDesc}).kind in IntegralTypes) @@ -692,7 +692,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode = if callee.kind notin {skProc, skConverter} or callee.isGenericRoutine: return - if n.typ != nil and not typeAllowed(n.typ, skConst): return + if n.typ != nil and typeAllowed(n.typ, skConst) != nil: return var call = newNodeIT(nkCall, n.info, n.typ) call.add(n.sons[0]) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 3b90337e5..565d4db06 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -92,10 +92,10 @@ proc semProc(c: PContext, n: PNode): PNode include semdestruct proc semDestructorCheck(c: PContext, n: PNode, flags: TExprFlags) {.inline.} = - if efAllowDestructor notin flags and n.kind in nkCallKinds+{nkObjConstr}: + if efAllowDestructor notin flags and + n.kind in nkCallKinds+{nkObjConstr,nkBracket}: if instantiateDestructor(c, n.typ) != nil: - localError(n.info, errGenerated, - "usage of a type with a destructor in a non destructible context") + localError(n.info, warnDestructor) # This still breaks too many things: when false: if efDetermineType notin flags and n.typ.kind == tyTypeDesc and @@ -380,8 +380,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = # this can only happen for errornous var statements: if typ == nil: continue - if not typeAllowed(typ, symkind): - localError(a.info, errXisNoType, typeToString(typ)) + typeAllowedCheck(a.info, typ, symkind) var tup = skipTypes(typ, {tyGenericInst}) if a.kind == nkVarTuple: if tup.kind != tyTuple: @@ -456,7 +455,7 @@ proc semConst(c: PContext, n: PNode): PNode = if typ == nil: localError(a.sons[2].info, errConstExprExpected) continue - if not typeAllowed(typ, skConst) and def.kind != nkNilLit: + if typeAllowed(typ, skConst) != nil and def.kind != nkNilLit: localError(a.info, errXisNoType, typeToString(typ)) continue v.typ = typ @@ -1187,6 +1186,8 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode = else: discard proc semStaticStmt(c: PContext, n: PNode): PNode = + #echo "semStaticStmt" + #writeStackTrace() let a = semStmt(c, n.sons[0]) n.sons[0] = a evalStaticStmt(c.module, a, c.p.owner) diff --git a/compiler/types.nim b/compiler/types.nim index e7841a9ab..78d390f13 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -85,8 +85,6 @@ proc analyseObjectWithTypeField*(t: PType): TTypeFieldResult # this does a complex analysis whether a call to ``objectInit`` needs to be # made or intializing of the type field suffices or if there is no type field # at all in this type. -proc typeAllowed*(t: PType, kind: TSymKind): bool -# implementation proc invalidGenericInst(f: PType): bool = result = f.kind == tyGenericInst and lastSon(f) == nil @@ -1027,22 +1025,21 @@ type TTypeAllowedFlags = set[TTypeAllowedFlag] proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, - flags: TTypeAllowedFlags = {}): bool + flags: TTypeAllowedFlags = {}): PType proc typeAllowedNode(marker: var IntSet, n: PNode, kind: TSymKind, - flags: TTypeAllowedFlags = {}): bool = - result = true + flags: TTypeAllowedFlags = {}): PType = if n != nil: result = typeAllowedAux(marker, n.typ, kind, flags) #if not result: debug(n.typ) - if result: + if result == nil: case n.kind of nkNone..nkNilLit: discard - else: - for i in countup(0, sonsLen(n) - 1): + else: + for i in countup(0, sonsLen(n) - 1): result = typeAllowedNode(marker, n.sons[i], kind, flags) - if not result: break + if result != nil: break proc matchType*(a: PType, pattern: openArray[tuple[k:TTypeKind, i:int]], last: TTypeKind): bool = @@ -1054,84 +1051,88 @@ proc matchType*(a: PType, pattern: openArray[tuple[k:TTypeKind, i:int]], result = a.kind == last proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, - flags: TTypeAllowedFlags = {}): bool = + flags: TTypeAllowedFlags = {}): PType = assert(kind in {skVar, skLet, skConst, skParam, skResult}) # if we have already checked the type, return true, because we stop the # evaluation if something is wrong: - result = true + result = nil if typ == nil: return - if containsOrIncl(marker, typ.id): return + if containsOrIncl(marker, typ.id): return var t = skipTypes(typ, abstractInst-{tyTypeDesc}) case t.kind of tyVar: - if kind == skConst: return false + if kind == skConst: return t var t2 = skipTypes(t.sons[0], abstractInst-{tyTypeDesc}) case t2.kind of tyVar: - result = taHeap in flags # ``var var`` is illegal on the heap: - of tyOpenArray: - result = kind == skParam and typeAllowedAux(marker, t2, kind, flags) + if taHeap notin flags: result = t2 # ``var var`` is illegal on the heap + of tyOpenArray: + if kind != skParam: result = t + else: result = typeAllowedAux(marker, t2, kind, flags) else: - result = kind in {skParam, skResult} and - typeAllowedAux(marker, t2, kind, flags) - of tyProc: + if kind notin {skParam, skResult}: result = t + else: result = typeAllowedAux(marker, t2, kind, flags) + of tyProc: for i in countup(1, sonsLen(t) - 1): result = typeAllowedAux(marker, t.sons[i], skParam, flags) - if not result: break - if result and t.sons[0] != nil: + if result != nil: break + if result.isNil and t.sons[0] != nil: result = typeAllowedAux(marker, t.sons[0], skResult, flags) of tyExpr, tyStmt, tyTypeDesc, tyStatic: - result = true + result = nil # XXX er ... no? these should not be allowed! of tyEmpty: - result = taField in flags + if taField notin flags: result = t of tyTypeClasses: - result = tfGenericTypeParam in t.flags or - taField notin flags + if not (tfGenericTypeParam in t.flags or taField notin flags): result = t of tyGenericBody, tyGenericParam, tyGenericInvokation, tyNone, tyForward, tyFromExpr, tyFieldAccessor: - result = false + result = t of tyNil: - result = kind == skConst + if kind != skConst: result = t of tyString, tyBool, tyChar, tyEnum, tyInt..tyBigNum, tyCString, tyPointer: - result = true - of tyOrdinal: - result = kind == skParam - of tyGenericInst, tyDistinct: + result = nil + of tyOrdinal: + if kind != skParam: result = t + of tyGenericInst, tyDistinct: result = typeAllowedAux(marker, lastSon(t), kind, flags) - of tyRange: - result = skipTypes(t.sons[0], abstractInst-{tyTypeDesc}).kind in - {tyChar, tyEnum, tyInt..tyFloat128} - of tyOpenArray, tyVarargs: - result = (kind == skParam) and typeAllowedAux(marker, t.sons[0], skVar, flags) - of tySequence: - result = t.sons[0].kind == tyEmpty or - typeAllowedAux(marker, t.sons[0], skVar, flags+{taHeap}) + of tyRange: + if skipTypes(t.sons[0], abstractInst-{tyTypeDesc}).kind notin + {tyChar, tyEnum, tyInt..tyFloat128}: result = t + of tyOpenArray, tyVarargs: + if kind != skParam: result = t + else: result = typeAllowedAux(marker, t.sons[0], skVar, flags) + of tySequence: + if t.sons[0].kind != tyEmpty: + result = typeAllowedAux(marker, t.sons[0], skVar, flags+{taHeap}) of tyArray: - result = t.sons[1].kind == tyEmpty or - typeAllowedAux(marker, t.sons[1], skVar, flags) + if t.sons[1].kind != tyEmpty: + result = typeAllowedAux(marker, t.sons[1], skVar, flags) of tyRef: - if kind == skConst: return false - result = typeAllowedAux(marker, t.lastSon, skVar, flags+{taHeap}) + if kind == skConst: result = t + else: result = typeAllowedAux(marker, t.lastSon, skVar, flags+{taHeap}) of tyPtr: result = typeAllowedAux(marker, t.lastSon, skVar, flags+{taHeap}) of tyArrayConstr, tySet, tyConst, tyMutable, tyIter: for i in countup(0, sonsLen(t) - 1): result = typeAllowedAux(marker, t.sons[i], kind, flags) - if not result: break + if result != nil: break of tyObject, tyTuple: - if kind == skConst and t.kind == tyObject: return false + if kind == skConst and t.kind == tyObject: return t let flags = flags+{taField} - for i in countup(0, sonsLen(t) - 1): + for i in countup(0, sonsLen(t) - 1): result = typeAllowedAux(marker, t.sons[i], kind, flags) - if not result: break - if result and t.n != nil: result = typeAllowedNode(marker, t.n, kind, flags) + if result != nil: break + if result.isNil and t.n != nil: + result = typeAllowedNode(marker, t.n, kind, flags) of tyProxy: # for now same as error node; we say it's a valid type as it should # prevent cascading errors: - result = true + result = nil -proc typeAllowed(t: PType, kind: TSymKind): bool = +proc typeAllowed*(t: PType, kind: TSymKind): PType = + # returns 'nil' on success and otherwise the part of the type that is + # wrong! var marker = initIntSet() result = typeAllowedAux(marker, t, kind, {}) diff --git a/koch.nim b/koch.nim index 13bcc3db1..432b9ff3d 100644 --- a/koch.nim +++ b/koch.nim @@ -61,6 +61,9 @@ Boot options: -d:nativeStacktrace use native stack traces (only for Mac OS X or Linux) -d:noCaas build Nimrod without CAAS support -d:avoidTimeMachine only for Mac OS X, excludes nimcache dir from backups +Web options: + --googleAnalytics:UA-... add the given google analytics code to the docs. To + build the official docs, use UA-48159761-1 """ proc exe(f: string): string = return addFileExt(f, ExeExt) @@ -356,6 +359,9 @@ of cmdArgument: of "clean": clean(op.cmdLineRest) of "web": web(op.cmdLineRest) of "website": website(op.cmdLineRest) + of "web0": + # undocumented command for Araq-the-merciful: + web(op.cmdLineRest & " --googleAnalytics:UA-48159761-1") of "pdf": pdf() of "csource", "csources": csource(op.cmdLineRest) of "zip": zip(op.cmdLineRest) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index d9f161d49..3c1401887 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -380,17 +380,16 @@ proc format(p: MultipartData): tuple[header, body: string] = result.body.add("--" & bound & "\c\L" & s) result.body.add("--" & bound & "--\c\L") -proc request*(url: string, httpMethod = httpGET, extraHeaders = "", - body = "", - sslContext: SSLContext = defaultSSLContext, - timeout = -1, userAgent = defUserAgent, - proxy: Proxy = nil): Response = - ## | Requests ``url`` with the specified ``httpMethod``. +proc request*(url: string, httpMethod: string, extraHeaders = "", + body = "", sslContext = defaultSSLContext, timeout = -1, + userAgent = defUserAgent, proxy: Proxy = nil): Response = + ## | Requests ``url`` with the custom method string specified by the + ## | ``httpMethod`` parameter. ## | Extra headers can be specified and must be seperated by ``\c\L`` ## | An optional timeout can be specified in miliseconds, if reading from the ## server takes longer than specified an ETimeout exception will be raised. var r = if proxy == nil: parseUri(url) else: proxy.url - var headers = substr($httpMethod, len("http")) + var headers = substr(httpMethod, len("http")) if proxy == nil: headers.add(" " & r.path) if r.query.len > 0: @@ -430,9 +429,19 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "", if body != "": s.send(body) - result = parseResponse(s, httpMethod != httpHEAD, timeout) + result = parseResponse(s, httpMethod != "httpHEAD", timeout) s.close() +proc request*(url: string, httpMethod = httpGET, extraHeaders = "", + body = "", sslContext = defaultSSLContext, timeout = -1, + userAgent = defUserAgent, proxy: Proxy = nil): Response = + ## | Requests ``url`` with the specified ``httpMethod``. + ## | Extra headers can be specified and must be seperated by ``\c\L`` + ## | An optional timeout can be specified in miliseconds, if reading from the + ## server takes longer than specified an ETimeout exception will be raised. + result = request(url, $httpMethod, extraHeaders, body, sslContext, timeout, + userAgent, proxy) + proc redirection(status: string): bool = const redirectionNRs = ["301", "302", "303", "307"] for i in items(redirectionNRs): @@ -556,9 +565,9 @@ proc downloadFile*(url: string, outputFilename: string, else: fileError("Unable to open file") -proc generateHeaders(r: Uri, httpMethod: HttpMethod, +proc generateHeaders(r: Uri, httpMethod: string, headers: StringTableRef): string = - result = substr($httpMethod, len("http")) + result = substr(httpMethod, len("http")) # TODO: Proxies result.add(" " & r.path) if r.query.len > 0: @@ -755,10 +764,10 @@ proc newConnection(client: AsyncHttpClient, url: Uri) {.async.} = client.currentURL = url client.connected = true -proc request*(client: AsyncHttpClient, url: string, httpMethod = httpGET, +proc request*(client: AsyncHttpClient, url: string, httpMethod: string, body = ""): Future[Response] {.async.} = ## Connects to the hostname specified by the URL and performs a request - ## using the method specified. + ## using the custom method string specified by ``httpMethod``. ## ## Connection will kept alive. Further requests on the same ``client`` to ## the same hostname will not require a new connection to be made. The @@ -771,13 +780,25 @@ proc request*(client: AsyncHttpClient, url: string, httpMethod = httpGET, if not client.headers.hasKey("user-agent") and client.userAgent != "": client.headers["User-Agent"] = client.userAgent - var headers = generateHeaders(r, httpMethod, client.headers) + var headers = generateHeaders(r, $httpMethod, client.headers) await client.socket.send(headers) if body != "": await client.socket.send(body) - result = await parseResponse(client, httpMethod != httpHEAD) + result = await parseResponse(client, httpMethod != "httpHEAD") + +proc request*(client: AsyncHttpClient, url: string, httpMethod = httpGET, + body = ""): Future[Response] = + ## Connects to the hostname specified by the URL and performs a request + ## using the method specified. + ## + ## Connection will kept alive. Further requests on the same ``client`` to + ## the same hostname will not require a new connection to be made. The + ## connection can be closed by using the ``close`` procedure. + ## + ## The returned future will complete once the request is completed. + result = request(client, url, $httpMethod, body) proc get*(client: AsyncHttpClient, url: string): Future[Response] {.async.} = ## Connects to the hostname specified by the URL and performs a GET request. diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index 29f6cd3ab..bd2564937 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -156,7 +156,7 @@ elif defined(linux): let fd = s.events[i].data.fd.SocketHandle var evSet: set[Event] = {} - if (s.events[i].events and EPOLLERR) != 0: evSet = evSet + {EvError} + if (s.events[i].events and EPOLLERR) != 0 or (s.events[i].events and EPOLLHUP) != 0: evSet = evSet + {EvError} if (s.events[i].events and EPOLLIN) != 0: evSet = evSet + {EvRead} if (s.events[i].events and EPOLLOUT) != 0: evSet = evSet + {EvWrite} let selectorKey = s.fds[fd] diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim index 1c1d973ee..8607066f3 100644 --- a/lib/pure/terminal.nim +++ b/lib/pure/terminal.nim @@ -185,13 +185,15 @@ proc eraseScreen* = var numwrote: DWORD var origin: TCOORD # is inititalized to 0, 0 var hStdout = conHandle + if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: raiseOSError(osLastError()) - if FillConsoleOutputCharacter(hStdout, ' ', scrbuf.dwSize.X*scrbuf.dwSize.Y, + let numChars = int32(scrbuf.dwSize.X)*int32(scrbuf.dwSize.Y) + + if FillConsoleOutputCharacter(hStdout, ' ', numChars, origin, addr(numwrote)) == 0: raiseOSError(osLastError()) - if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, - scrbuf.dwSize.X * scrbuf.dwSize.Y, + if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, numChars, origin, addr(numwrote)) == 0: raiseOSError(osLastError()) setCursorXPos(0) diff --git a/lib/system.nim b/lib/system.nim index 57d92b28e..69a77b89b 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2509,7 +2509,7 @@ when not defined(JS): #and not defined(NimrodVM): initGC() when not defined(NimrodVM): - proc setControlCHook*(hook: proc () {.noconv.}) + proc setControlCHook*(hook: proc () {.noconv.} not nil) ## allows you to override the behaviour of your application when CTRL+C ## is pressed. Only one such hook is supported. diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim index 3ef0d9ce3..417a8634f 100644 --- a/lib/system/excpt.nim +++ b/lib/system/excpt.nim @@ -341,7 +341,7 @@ when not defined(noSignalHandler): registerSignalHandler() # call it in initialization section -proc setControlCHook(hook: proc () {.noconv.}) = +proc setControlCHook(hook: proc () {.noconv.} not nil) = # ugly cast, but should work on all architectures: type TSignalHandler = proc (sig: cint) {.noconv, benign.} c_signal(SIGINT, cast[TSignalHandler](hook)) diff --git a/tests/generics/tgeneric_inheritance.nim b/tests/generics/tgeneric_inheritance.nim index 66b5a6c69..432228797 100644 --- a/tests/generics/tgeneric_inheritance.nim +++ b/tests/generics/tgeneric_inheritance.nim @@ -1,5 +1,5 @@ discard """ - output: '0.0' + output: "0.0" """ # bug #1919 diff --git a/tests/generics/tmetafield.nim b/tests/generics/tmetafield.nim index bbfca7e3c..7a2375abe 100644 --- a/tests/generics/tmetafield.nim +++ b/tests/generics/tmetafield.nim @@ -2,7 +2,7 @@ discard """ cmd: "nim check $options $file" errormsg: "'proc' is not a concrete type" errormsg: "'Foo' is not a concrete type." - errormsg: "invalid type: 'TBaseMed'" + errormsg: "invalid type: 'proc' in this context: 'TBaseMed'" """ type diff --git a/web/community.txt b/web/community.txt index 5c0d30856..5d9343c98 100644 --- a/web/community.txt +++ b/web/community.txt @@ -14,6 +14,16 @@ Nim's Community .. container:: standout + Mailing list + ------------ + + The mailing list can be found here: http://www.freelists.org/list/nim-dev + There is no consensus yet about what is discussed via the forum as opposed + to the mailing list. Join whatever you like! + + +.. container:: standout + IRC ---- |