diff options
95 files changed, 1030 insertions, 661 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index d487b5380..1a5ae8aab 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -459,7 +459,7 @@ type tfNeedsInit, # type constains a "not nil" constraint somewhere or some # other type so that it requires inititalization - tfHasShared, # type constains a "shared" constraint modifier somewhere + tfVarIsPtr, # 'var' type is translated like 'ptr' even in C++ mode tfHasMeta, # type contains "wildcard" sub-types such as generic params # or other type classes tfHasGCedMem, # type contains GC'ed memory @@ -522,7 +522,7 @@ const skError* = skUnknown # type flags that are essential for type equality: - eqTypeFlags* = {tfIterator, tfShared, tfNotNil} + eqTypeFlags* = {tfIterator, tfShared, tfNotNil, tfVarIsPtr} type TMagic* = enum # symbols that require compiler magic: @@ -655,7 +655,6 @@ type locGlobalVar, # location is a global variable locParam, # location is a parameter locField, # location is a record field - locArrayElem, # location is an array element locExpr, # "location" is really an expression locProc, # location is a proc (an address of a procedure) locData, # location is a constant @@ -669,14 +668,15 @@ type lfDynamicLib, # link symbol to dynamic library lfExportLib, # export symbol for dynamic library generation lfHeader, # include header file for symbol - lfImportCompilerProc # ``importc`` of a compilerproc + lfImportCompilerProc, # ``importc`` of a compilerproc + lfSingleUse # no location yet and will only be used once TStorageLoc* = enum OnUnknown, # location is unknown (stack, heap or static) OnStack, # location is on hardware stack OnHeap # location is on heap or global # (reference counting needed) TLocFlags* = set[TLocFlag] - TLoc*{.final.} = object + TLoc* = object k*: TLocKind # kind of location s*: TStorageLoc flags*: TLocFlags # location's flags @@ -1348,7 +1348,7 @@ proc isGCedMem*(t: PType): bool {.inline.} = proc propagateToOwner*(owner, elem: PType) = const HaveTheirOwnEmpty = {tySequence, tySet} - owner.flags = owner.flags + (elem.flags * {tfHasShared, tfHasMeta}) + owner.flags = owner.flags + (elem.flags * {tfHasMeta}) if tfNotNil in elem.flags: if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvokation}: owner.flags.incl tfNotNil @@ -1359,9 +1359,6 @@ proc propagateToOwner*(owner, elem: PType) = if owner.kind in HaveTheirOwnEmpty: discard else: owner.flags.incl tfNeedsInit - if tfShared in elem.flags: - owner.flags.incl tfHasShared - if elem.isMetaType: owner.flags.incl tfHasMeta diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index cb8dcc25b..b9fc694cb 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -45,12 +45,20 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, genAssignment(p, d, tmp, {}) # no need for deep copying else: app(pl, ~")") - if d.k == locNone: getTemp(p, typ.sons[0], d) - assert(d.t != nil) # generate an assignment to d: - var list: TLoc - initLoc(list, locCall, d.t, OnUnknown) - list.r = pl - genAssignment(p, d, list, {}) # no need for deep copying + if p.module.compileToCpp and lfSingleUse in d.flags: + # do not generate spurious temporaries for C++! For C we're better off + # with them to prevent undefined behaviour and because the codegen + # is free to emit expressions multiple times! + d.k = locCall + d.r = pl + excl d.flags, lfSingleUse + else: + if d.k == locNone: getTemp(p, typ.sons[0], d) + assert(d.t != nil) # generate an assignment to d: + var list: TLoc + initLoc(list, locCall, d.t, OnUnknown) + list.r = pl + genAssignment(p, d, list, {}) # no need for deep copying else: app(pl, ~");$n") line(p, cpsStmts, pl) @@ -90,7 +98,8 @@ proc openArrayLoc(p: BProc, n: PNode): PRope = of tyOpenArray, tyVarargs, tyArray, tyArrayConstr: "($1)+($2), ($3)-($2)+1" of tyString, tySequence: - if skipTypes(n.typ, abstractInst).kind == tyVar: + if skipTypes(n.typ, abstractInst).kind == tyVar and + not compileToCpp(p.module): "(*$1)->data+($2), ($3)-($2)+1" else: "$1->data+($2), ($3)-($2)+1" @@ -102,7 +111,8 @@ proc openArrayLoc(p: BProc, n: PNode): PRope = of tyOpenArray, tyVarargs: result = ropef("$1, $1Len0", [rdLoc(a)]) of tyString, tySequence: - if skipTypes(n.typ, abstractInst).kind == tyVar: + if skipTypes(n.typ, abstractInst).kind == tyVar and + not compileToCpp(p.module): result = ropef("(*$1)->data, (*$1)->$2", [a.rdLoc, lenField(p)]) else: result = ropef("$1->data, $1->$2", [a.rdLoc, lenField(p)]) @@ -114,8 +124,8 @@ proc genArgStringToCString(p: BProc, n: PNode): PRope {.inline.} = var a: TLoc initLocExpr(p, n.sons[0], a) result = ropef("$1->data", [a.rdLoc]) - -proc genArg(p: BProc, n: PNode, param: PSym): PRope = + +proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): PRope = var a: TLoc if n.kind == nkStringToCString: result = genArgStringToCString(p, n) @@ -123,10 +133,22 @@ proc genArg(p: BProc, n: PNode, param: PSym): PRope = var n = if n.kind != nkHiddenAddr: n else: n.sons[0] result = openArrayLoc(p, n) elif ccgIntroducedPtr(param): - initLocExpr(p, n, a) + initLocExprSingleUse(p, n, a) result = addrLoc(a) + elif p.module.compileToCpp and param.typ.kind == tyVar and + n.kind == nkHiddenAddr: + initLocExprSingleUse(p, n.sons[0], a) + # if the proc is 'importc'ed but not 'importcpp'ed then 'var T' still + # means '*T'. See posix.nim for lots of examples that do that in the wild. + let callee = call.sons[0] + if callee.kind == nkSym and + {sfImportC, sfInfixCall, sfCompilerProc} * callee.sym.flags == {sfImportC} and + {lfHeader, lfNoDecl} * callee.sym.loc.flags != {}: + result = addrLoc(a) + else: + result = rdLoc(a) else: - initLocExpr(p, n, a) + initLocExprSingleUse(p, n, a) result = rdLoc(a) proc genArgNoParam(p: BProc, n: PNode): PRope = @@ -134,7 +156,7 @@ proc genArgNoParam(p: BProc, n: PNode): PRope = if n.kind == nkStringToCString: result = genArgStringToCString(p, n) else: - initLocExpr(p, n, a) + initLocExprSingleUse(p, n, a) result = rdLoc(a) proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) = @@ -152,7 +174,7 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) = if params != nil: app(params, ~", ") if i < sonsLen(typ): assert(typ.n.sons[i].kind == nkSym) - app(params, genArg(p, ri.sons[i], typ.n.sons[i].sym)) + app(params, genArg(p, ri.sons[i], typ.n.sons[i].sym, ri)) else: app(params, genArgNoParam(p, ri.sons[i])) fixupCall(p, le, ri, d, op.r, params) @@ -178,7 +200,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = assert(sonsLen(typ) == sonsLen(typ.n)) if i < sonsLen(typ): assert(typ.n.sons[i].kind == nkSym) - app(pl, genArg(p, ri.sons[i], typ.n.sons[i].sym)) + app(pl, genArg(p, ri.sons[i], typ.n.sons[i].sym, ri)) else: app(pl, genArgNoParam(p, ri.sons[i])) if i < length - 1: app(pl, ~", ") @@ -274,26 +296,28 @@ proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType): PRope = assert(typ.n.sons[i].kind == nkSym) # if the parameter is lying (tyVar) and thus we required an additional deref, # skip the deref: + var ri = ri[i] + while ri.kind == nkObjDownConv: ri = ri[0] if typ.sons[i].kind == tyVar: - let x = if ri[i].kind == nkHiddenAddr: ri[i][0] else: ri[i] - if x.kind in {nkHiddenDeref, nkDerefExpr}: - result = genArgNoParam(p, x[0]) - result.app("->") - elif x.typ.kind in {tyVar, tyPtr}: + let x = if ri.kind == nkHiddenAddr: ri[0] else: ri + if x.typ.kind == tyPtr: result = genArgNoParam(p, x) result.app("->") + elif x.kind in {nkHiddenDeref, nkDerefExpr} and x[0].typ.kind == tyPtr: + result = genArgNoParam(p, x[0]) + result.app("->") else: result = genArgNoParam(p, x) result.app(".") elif typ.sons[i].kind == tyPtr: - if ri.sons[i].kind in {nkAddr, nkHiddenAddr}: - result = genArgNoParam(p, ri.sons[i][0]) + if ri.kind in {nkAddr, nkHiddenAddr}: + result = genArgNoParam(p, ri[0]) result.app(".") else: - result = genArgNoParam(p, ri.sons[i]) + result = genArgNoParam(p, ri) result.app("->") else: - result = genArgNoParam(p, ri.sons[i]) #, typ.n.sons[i].sym) + result = genArgNoParam(p, ri) #, typ.n.sons[i].sym) result.app(".") proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): PRope = @@ -367,12 +391,20 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) = # simpler version of 'fixupCall' that works with the pl+params combination: var typ = skipTypes(ri.sons[0].typ, abstractInst) if typ.sons[0] != nil: - if d.k == locNone: getTemp(p, typ.sons[0], d) - assert(d.t != nil) # generate an assignment to d: - var list: TLoc - initLoc(list, locCall, d.t, OnUnknown) - list.r = pl - genAssignment(p, d, list, {}) # no need for deep copying + if p.module.compileToCpp and lfSingleUse in d.flags: + # do not generate spurious temporaries for C++! For C we're better off + # with them to prevent undefined behaviour and because the codegen + # is free to emit expressions multiple times! + d.k = locCall + d.r = pl + excl d.flags, lfSingleUse + else: + if d.k == locNone: getTemp(p, typ.sons[0], d) + assert(d.t != nil) # generate an assignment to d: + var list: TLoc + initLoc(list, locCall, d.t, OnUnknown) + list.r = pl + genAssignment(p, d, list, {}) # no need for deep copying else: app(pl, ~";$n") line(p, cpsStmts, pl) @@ -400,12 +432,12 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) = assert(sonsLen(typ) == sonsLen(typ.n)) if length > 1: - app(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym)) + app(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym, ri)) app(pl, ~" ") app(pl, op.r) if length > 2: app(pl, ~": ") - app(pl, genArg(p, ri.sons[2], typ.n.sons[2].sym)) + app(pl, genArg(p, ri.sons[2], typ.n.sons[2].sym, ri)) for i in countup(3, length-1): assert(sonsLen(typ) == sonsLen(typ.n)) if i >= sonsLen(typ): @@ -415,7 +447,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) = app(pl, ~" ") app(pl, param.name.s) app(pl, ~": ") - app(pl, genArg(p, ri.sons[i], param)) + app(pl, genArg(p, ri.sons[i], param, ri)) if typ.sons[0] != nil: if isInvalidReturnType(typ.sons[0]): if sonsLen(ri) > 1: app(pl, ~" ") diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 93bb5dbf5..9b45c4492 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -83,7 +83,9 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): PRope = else: result = toRope("NIM_NIL") of nkStrLit..nkTripleStrLit: - if skipTypes(ty, abstractVarRange).kind == tyString: + if n.strVal.isNil: + result = ropecg(p.module, "((#NimStringDesc*) NIM_NIL)", []) + elif skipTypes(ty, abstractVarRange).kind == tyString: var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId) if id == gBackendId: # string literal not found in the cache: @@ -662,9 +664,14 @@ proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) = ropef(unArithTab[op], [rdLoc(a), toRope(getSize(t) * 8), getSimpleTypeDesc(p.module, e.typ)])) +proc isCppRef(p: BProc; typ: PType): bool {.inline.} = + result = p.module.compileToCpp and + skipTypes(typ, abstractInst).kind == tyVar and + tfVarIsPtr notin skipTypes(typ, abstractInst).flags + proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) = let mt = mapType(e.sons[0].typ) - if mt in {ctArray, ctPtrToArray} and not enforceDeref: + if (mt in {ctArray, ctPtrToArray} and not enforceDeref): # XXX the amount of hacks for C's arrays is incredible, maybe we should # simply wrap them in a struct? --> Losing auto vectorization then? #if e[0].kind != nkBracketExpr: @@ -672,12 +679,17 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) = expr(p, e.sons[0], d) else: var a: TLoc - initLocExpr(p, e.sons[0], a) - case skipTypes(a.t, abstractInst).kind + initLocExprSingleUse(p, e.sons[0], a) + let typ = skipTypes(a.t, abstractInst) + case typ.kind of tyRef: d.s = OnHeap of tyVar: d.s = OnUnknown + if tfVarIsPtr notin typ.flags and p.module.compileToCpp and + e.kind == nkHiddenDeref: + putIntoDest(p, d, e.typ, rdLoc(a)) + return of tyPtr: d.s = OnUnknown # BUGFIX! else: internalError(e.info, "genDeref " & $a.t.kind) @@ -698,7 +710,7 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) = initLocExpr(p, e.sons[0], a) putIntoDest(p, d, e.typ, con("&", a.r)) #Message(e.info, warnUser, "HERE NEW &") - elif mapType(e.sons[0].typ) == ctArray: + elif mapType(e.sons[0].typ) == ctArray or isCppRef(p, e.sons[0].typ): expr(p, e.sons[0], d) else: var a: TLoc @@ -916,6 +928,7 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) = L: TLabel tmp: TLoc getTemp(p, e.typ, tmp) # force it into a temp! + inc p.splitDecls expr(p, e.sons[1], tmp) L = getLabel(p) if m == mOr: @@ -928,6 +941,7 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) = d = tmp else: genAssignment(p, d, tmp, {}) # no need for deep copying + dec p.splitDecls proc genEcho(p: BProc, n: PNode) = # this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)`` @@ -938,7 +952,7 @@ proc genEcho(p: BProc, n: PNode) = var a: TLoc for i in countup(0, n.len-1): initLocExpr(p, n.sons[i], a) - appf(args, ", ($1)->data", [rdLoc(a)]) + appf(args, ", $1? ($1)->data:\"nil\"", [rdLoc(a)]) linefmt(p, cpsStmts, "printf($1$2);$n", makeCString(repeatStr(n.len, "%s") & tnl), args) @@ -1236,7 +1250,8 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) = var t = skipTypes(a.t, abstractInst) while t.kind in {tyVar, tyPtr, tyRef}: if t.kind != tyVar: nilCheck = r - r = rfmt(nil, "(*$1)", r) + if t.kind != tyVar or not p.module.compileToCpp: + r = rfmt(nil, "(*$1)", r) t = skipTypes(t.lastSon, typedescInst) if not p.module.compileToCpp: while t.kind == tyObject and t.sons[0] != nil: @@ -1863,7 +1878,8 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) = var t = skipTypes(a.t, abstractInst) while t.kind in {tyVar, tyPtr, tyRef}: if t.kind != tyVar: nilCheck = r - r = ropef("(*$1)", [r]) + if t.kind != tyVar or not p.module.compileToCpp: + r = ropef("(*$1)", [r]) t = skipTypes(t.lastSon, abstractInst) if not p.module.compileToCpp: while t.kind == tyObject and t.sons[0] != nil: @@ -2073,8 +2089,8 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = genAsgn(p, n, fastAsgn=p.prc != nil) of nkDiscardStmt: if n.sons[0].kind != nkEmpty: - var a: TLoc genLineDir(p, n) + var a: TLoc initLocExpr(p, n.sons[0], a) of nkAsmStmt: genAsmStmt(p, n) of nkTryStmt: @@ -2159,7 +2175,7 @@ proc genConstExpr(p: BProc, n: PNode): PRope = var cs: TBitSet toBitSet(n, cs) result = genRawSetData(cs, int(getSize(n.typ))) - of nkBracket, nkPar, nkClosure: + of nkBracket, nkPar, nkClosure, nkObjConstr: var t = skipTypes(n.typ, abstractInst) if t.kind == tySequence: result = genConstSeq(p, n, t) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index f0870a5df..18705c974 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -202,8 +202,19 @@ proc genSingleVar(p: BProc, a: PNode) = genVarPrototypeAux(generatedHeader, v) registerGcRoot(p, v) else: + let imm = isAssignedImmediately(a.sons[2]) + if imm and p.module.compileToCpp and p.splitDecls == 0: + # C++ really doesn't like things like 'Foo f; f = x' as that invokes a + # parameterless constructor followed by an assignment operator. So we + # generate better code here: + genLineDir(p, a) + let decl = localVarDecl(p, v) + var tmp: TLoc + initLocExprSingleUse(p, a.sons[2], tmp) + lineF(p, cpsStmts, "$# = $#;$n", decl, tmp.rdLoc) + return assignLocalVar(p, v) - initLocalVar(p, v, isAssignedImmediately(a.sons[2])) + initLocalVar(p, v, imm) if a.sons[2].kind != nkEmpty: genLineDir(targetProc, a) @@ -242,16 +253,7 @@ proc genConstStmt(p: BProc, t: PNode) = elif c.typ.kind in ConstantDataTypes and lfNoDecl notin c.loc.flags and c.ast.len != 0: if not emitLazily(c): requestConstImpl(p, c) - when false: - # generate the data: - fillLoc(c.loc, locData, c.typ, mangleName(c), OnUnknown) - if sfImportc in c.flags: - appf(p.module.s[cfsData], "extern NIM_CONST $1 $2;$n", - [getTypeDesc(p.module, c.typ), c.loc.r]) - else: - appf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n", - [getTypeDesc(p.module, c.typ), c.loc.r, genConstExpr(p, c.ast)]) - + proc genIf(p: BProc, n: PNode, d: var TLoc) = # # { if (!expr1) goto L1; @@ -275,17 +277,22 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) = let it = n.sons[i] if it.len == 2: when newScopeForIf: startBlock(p) - initLocExpr(p, it.sons[0], a) + initLocExprSingleUse(p, it.sons[0], a) lelse = getLabel(p) inc(p.labels) - lineFF(p, cpsStmts, "if (!$1) goto $2;$n", - "br i1 $1, label %LOC$3, label %$2$nLOC$3: $n", - [rdLoc(a), lelse, toRope(p.labels)]) + lineF(p, cpsStmts, "if (!$1) goto $2;$n", + [rdLoc(a), lelse]) when not newScopeForIf: startBlock(p) - expr(p, it.sons[1], d) + if p.module.compileToCpp: + # avoid "jump to label crosses initialization" error: + app(p.s(cpsStmts), "{") + expr(p, it.sons[1], d) + app(p.s(cpsStmts), "}") + else: + expr(p, it.sons[1], d) endBlock(p) if sonsLen(n) > 1: - lineFF(p, cpsStmts, "goto $1;$n", "br label %$1$n", [lend]) + lineF(p, cpsStmts, "goto $1;$n", [lend]) fixLabel(p, lelse) elif it.len == 1: startBlock(p) @@ -344,7 +351,7 @@ proc genReturnStmt(p: BProc, t: PNode) = # consume it before we return. var safePoint = p.finallySafePoints[p.finallySafePoints.len-1] linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", safePoint) - lineFF(p, cpsStmts, "goto BeforeRet;$n", "br label %BeforeRet$n", []) + lineF(p, cpsStmts, "goto BeforeRet;$n", []) proc genComputedGoto(p: BProc; n: PNode) = # first pass: Generate array of computed labels: diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 90996d9cd..0220d2066 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -27,17 +27,7 @@ proc isKeyword(w: PIdent): bool = proc mangleName(s: PSym): PRope = result = s.loc.r - if result == nil: - if gCmd == cmdCompileToLLVM: - case s.kind - of skProc, skMethod, skConverter, skConst, skIterators: - result = ~"@" - of skVar, skForVar, skResult, skLet: - if sfGlobal in s.flags: result = ~"@" - else: result = ~"%" - of skTemp, skParam, skType, skEnumField, skModule: - result = ~"%" - else: internalError(s.info, "mangleName") + if result == nil: when oKeepVariableNames: let keepOrigName = s.kind in skLocalVars - {skForVar} and {sfFromGeneric, sfGlobal, sfShadowed, sfGenSym} * s.flags == {} and @@ -103,13 +93,11 @@ proc typeName(typ: PType): PRope = else: ~"TY" proc getTypeName(typ: PType): PRope = - if (typ.sym != nil) and ({sfImportc, sfExportc} * typ.sym.flags != {}) and - (gCmd != cmdCompileToLLVM): + if typ.sym != nil and {sfImportc, sfExportc} * typ.sym.flags != {}: result = typ.sym.loc.r else: if typ.loc.r == nil: - typ.loc.r = if gCmd != cmdCompileToLLVM: con(typ.typeName, typ.id.toRope) - else: con([~"%", typ.typeName, typ.id.toRope]) + typ.loc.r = con(typ.typeName, typ.id.toRope) result = typ.loc.r if result == nil: internalError("getTypeName: " & $typ.kind) @@ -161,7 +149,13 @@ proc mapType(typ: PType): TCTypeKind = proc mapReturnType(typ: PType): TCTypeKind = if skipTypes(typ, typedescInst).kind == tyArray: result = ctPtr else: result = mapType(typ) - + +proc isImportedType(t: PType): bool = + 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 getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope proc needsComplexAssignment(typ: PType): bool = result = containsGarbageCollectedRef(typ) @@ -170,19 +164,20 @@ proc isObjLackingTypeField(typ: PType): bool {.inline.} = result = (typ.kind == tyObject) and ((tfFinal in typ.flags) and (typ.sons[0] == nil) or isPureObject(typ)) -proc isInvalidReturnType(rettype: PType): bool = +proc isInvalidReturnType(rettype: PType): bool = # Arrays and sets cannot be returned by a C procedure, because C is # such a poor programming language. # We exclude records with refs too. This enhances efficiency and # is necessary for proper code generation of assignments. if rettype == nil: result = true - else: + else: case mapType(rettype) - of ctArray: + of ctArray: result = not (skipTypes(rettype, typedescInst).kind in {tyVar, tyRef, tyPtr}) of ctStruct: let t = skipTypes(rettype, typedescInst) + if rettype.isImportedCppType or t.isImportedCppType: return false result = needsComplexAssignment(t) or (t.kind == tyObject and not isObjLackingTypeField(t)) else: result = false @@ -193,9 +188,6 @@ const "N_SYSCALL", # this is probably not correct for all platforms, # but one can #define it to what one wants "N_INLINE", "N_NOINLINE", "N_FASTCALL", "N_CLOSURE", "N_NOCONV"] - CallingConvToStrLLVM: array[TCallingConvention, string] = ["fastcc $1", - "stdcall $1", "ccc $1", "safecall $1", "syscall $1", "$1 alwaysinline", - "$1 noinline", "fastcc $1", "ccc $1", "$1"] proc cacheGetType(tab: TIdTable, key: PType): PRope = # returns nil if we need to declare this type @@ -277,32 +269,26 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var PRope, # this fixes the 'sort' bug: if param.typ.kind == tyVar: param.loc.s = OnUnknown # need to pass hidden parameter: - appff(params, ", NI $1Len$2", ", @NI $1Len$2", [param.loc.r, j.toRope]) + appf(params, ", NI $1Len$2", [param.loc.r, j.toRope]) inc(j) arr = arr.sons[0] - if (t.sons[0] != nil) and isInvalidReturnType(t.sons[0]): + if (t.sons[0] != nil) and isInvalidReturnType(t.sons[0]): var arr = t.sons[0] if params != nil: app(params, ", ") app(params, getTypeDescAux(m, arr, check)) - if (mapReturnType(t.sons[0]) != ctArray) or (gCmd == cmdCompileToLLVM): + if (mapReturnType(t.sons[0]) != ctArray): app(params, "*") - appff(params, " Result", " @Result", []) + appf(params, " Result", []) if t.callConv == ccClosure and declareEnvironment: if params != nil: app(params, ", ") app(params, "void* ClEnv") if tfVarargs in t.flags: if params != nil: app(params, ", ") app(params, "...") - if params == nil and gCmd != cmdCompileToLLVM: app(params, "void)") + if params == nil: app(params, "void)") else: app(params, ")") params = con("(", params) -proc isImportedType(t: PType): bool = - 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): result = getTypeName(t) @@ -421,14 +407,18 @@ 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.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: - # 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]) + # for importcpp'ed objects, we only need to set field.loc, but don't + # have to recurse via 'getTypeDescAux'. And not doing so prevents problems + # with heavily templatized C++ code: + if not isImportedCppType(rectype): + 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: + # 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 = @@ -493,13 +483,16 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = if t.sym != nil: useHeader(m, t.sym) result = getTypePre(m, t) if result != nil: return - if containsOrIncl(check, t.id): + if containsOrIncl(check, t.id): + if isImportedCppType(typ) or isImportedCppType(t): return internalError("cannot generate C type for: " & typeToString(typ)) # XXX: this BUG is hard to fix -> we need to introduce helper structs, # but determining when this needs to be done is hard. We should split # C type generation into an analysis and a code generation phase somehow. case t.kind - of tyRef, tyPtr, tyVar: + of tyRef, tyPtr, tyVar: + var star = if t.kind == tyVar and tfVarIsPtr notin typ.flags and + compileToCpp(m): "&" else: "*" var et = t.lastSon var etB = et.skipTypes(abstractInst) if etB.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}: @@ -507,27 +500,28 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope = # ``var set[char]`` in `getParamTypeDesc` et = elemType(etB) etB = et.skipTypes(abstractInst) + star[0] = '*' case etB.kind of tyObject, tyTuple: if isImportedCppType(etB) and et.kind == tyGenericInst: - result = con(getTypeDescAux(m, et, check), "*") + result = con(getTypeDescAux(m, et, check), star) else: # no restriction! We have a forward declaration for structs let x = getUniqueType(etB) let name = getTypeForward(m, x) - result = con(name, "*") + result = con(name, star) idTablePut(m.typeCache, t, result) pushType(m, x) of tySequence: # no restriction! We have a forward declaration for structs let x = getUniqueType(etB) let name = getTypeForward(m, x) - result = con(name, "**") + result = con(name, "*" & star) idTablePut(m.typeCache, t, result) pushType(m, x) else: # else we have a strong dependency :-( - result = con(getTypeDescAux(m, et, check), "*") + result = con(getTypeDescAux(m, et, check), star) idTablePut(m.typeCache, t, result) of tyOpenArray, tyVarargs: result = con(getTypeDescAux(m, t.sons[0], check), "*") @@ -670,7 +664,7 @@ proc genProcHeader(m: BModule, prc: PSym): PRope = rettype, params: PRope genCLineDir(result, prc.info) # using static is needed for inline procs - if gCmd != cmdCompileToLLVM and lfExportLib in prc.loc.flags: + if lfExportLib in prc.loc.flags: if m.isHeaderFile: result.app "N_LIB_IMPORT " else: @@ -696,16 +690,7 @@ proc getNimNode(m: BModule): PRope = result = ropef("$1[$2]", [m.typeNodesName, toRope(m.typeNodes)]) inc(m.typeNodes) -when false: - proc getNimType(m: BModule): PRope = - result = ropef("$1[$2]", [m.nimTypesName, toRope(m.nimTypes)]) - inc(m.nimTypes) - - proc allocMemTI(m: BModule, typ: PType, name: PRope) = - var tmp = getNimType(m) - appf(m.s[cfsTypeInit2], "$2 = &$1;$n", [tmp, name]) - -proc genTypeInfoAuxBase(m: BModule, typ: PType, name, base: PRope) = +proc genTypeInfoAuxBase(m: BModule; typ, origType: PType; name, base: PRope) = var nimtypeKind: int #allocMemTI(m, typ, name) if isObjLackingTypeField(typ): @@ -715,6 +700,7 @@ proc genTypeInfoAuxBase(m: BModule, typ: PType, name, base: PRope) = var size: PRope if tfIncompleteStruct in typ.flags: size = toRope"void*" + elif m.compileToCpp: size = getTypeDesc(m, origType) else: size = getTypeDesc(m, typ) appf(m.s[cfsTypeInit3], "$1.size = sizeof($2);$n" & "$1.kind = $3;$n" & "$1.base = $4;$n", @@ -730,13 +716,13 @@ proc genTypeInfoAuxBase(m: BModule, typ: PType, name, base: PRope) = appf(m.s[cfsVars], "TNimType $1; /* $2 */$n", [name, toRope(typeToString(typ))]) -proc genTypeInfoAux(m: BModule, typ: PType, name: PRope) = +proc genTypeInfoAux(m: BModule, typ, origType: PType, name: PRope) = var base: PRope if (sonsLen(typ) > 0) and (typ.sons[0] != nil): base = genTypeInfo(m, typ.sons[0]) else: base = toRope("0") - genTypeInfoAuxBase(m, typ, name, base) + genTypeInfoAuxBase(m, typ, origType, name, base) proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): PRope = # bugfix: we need to search the type that contains the discriminator: @@ -814,11 +800,12 @@ proc genObjectFields(m: BModule, typ: PType, n: PNode, expr: PRope) = field.loc.r, genTypeInfo(m, field.typ), makeCString(field.name.s)]) else: internalError(n.info, "genObjectFields") -proc genObjectInfo(m: BModule, typ: PType, name: PRope) = - if typ.kind == tyObject: genTypeInfoAux(m, typ, name) - else: genTypeInfoAuxBase(m, typ, name, toRope("0")) +proc genObjectInfo(m: BModule, typ, origType: PType, name: PRope) = + if typ.kind == tyObject: genTypeInfoAux(m, typ, origType, name) + else: genTypeInfoAuxBase(m, typ, origType, name, toRope("0")) var tmp = getNimNode(m) - genObjectFields(m, typ, typ.n, tmp) + if not isImportedCppType(typ): + genObjectFields(m, typ, typ.n, tmp) appf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [name, tmp]) var t = typ.sons[0] while t != nil: @@ -827,7 +814,7 @@ proc genObjectInfo(m: BModule, typ: PType, name: PRope) = t = t.sons[0] proc genTupleInfo(m: BModule, typ: PType, name: PRope) = - genTypeInfoAuxBase(m, typ, name, toRope("0")) + genTypeInfoAuxBase(m, typ, typ, name, toRope("0")) var expr = getNimNode(m) var length = sonsLen(typ) if length > 0: @@ -854,7 +841,7 @@ proc genEnumInfo(m: BModule, typ: PType, name: PRope) = # optimizations here: The ``typ`` field is never set, as it is redundant # anyway. We generate a cstring array and a loop over it. Exceptional # positions will be reset after the loop. - genTypeInfoAux(m, typ, name) + genTypeInfoAux(m, typ, typ, name) var nodePtrs = getTempName() var length = sonsLen(typ.n) appf(m.s[cfsTypeInit1], "static TNimNode* $1[$2];$n", @@ -894,13 +881,13 @@ proc genEnumInfo(m: BModule, typ: PType, name: PRope) = proc genSetInfo(m: BModule, typ: PType, name: PRope) = assert(typ.sons[0] != nil) - genTypeInfoAux(m, typ, name) + genTypeInfoAux(m, typ, typ, name) var tmp = getNimNode(m) appf(m.s[cfsTypeInit3], "$1.len = $2; $1.kind = 0;$n" & "$3.node = &$1;$n", [tmp, toRope(firstOrd(typ)), name]) proc genArrayInfo(m: BModule, typ: PType, name: PRope) = - genTypeInfoAuxBase(m, typ, name, genTypeInfo(m, typ.sons[1])) + genTypeInfoAuxBase(m, typ, typ, name, genTypeInfo(m, typ.sons[1])) proc fakeClosureType(owner: PSym): PType = # we generate the same RTTI as for a tuple[pointer, ref tuple[]] @@ -946,23 +933,23 @@ proc genTypeInfo(m: BModule, t: PType): PRope = case t.kind of tyEmpty: result = toRope"0" of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar: - genTypeInfoAuxBase(m, t, result, toRope"0") + genTypeInfoAuxBase(m, t, t, result, toRope"0") of tyProc: if t.callConv != ccClosure: - genTypeInfoAuxBase(m, t, result, toRope"0") + genTypeInfoAuxBase(m, t, t, result, toRope"0") else: genTupleInfo(m, fakeClosureType(t.owner), result) of tySequence, tyRef: - genTypeInfoAux(m, t, result) + genTypeInfoAux(m, t, t, result) if gSelectedGC >= gcMarkAndSweep: let markerProc = genTraverseProc(m, t, tiNew) appf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [result, markerProc]) - of tyPtr, tyRange: genTypeInfoAux(m, t, result) + of tyPtr, tyRange: genTypeInfoAux(m, t, t, result) of tyArrayConstr, tyArray: genArrayInfo(m, t, result) of tySet: genSetInfo(m, t, result) of tyEnum: genEnumInfo(m, t, result) - of tyObject: genObjectInfo(m, t, result) - of tyTuple: + of tyObject: genObjectInfo(m, t, origType, result) + of tyTuple: # if t.n != nil: genObjectInfo(m, t, result) # else: # BUGFIX: use consistently RTTI without proper field names; otherwise diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 480c131ae..a606cb5b9 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -25,15 +25,6 @@ when options.hasTinyCBackend: var generatedHeader: BModule -proc ropeff(cformat, llvmformat: string, args: varargs[PRope]): PRope = - if gCmd == cmdCompileToLLVM: result = ropef(llvmformat, args) - else: result = ropef(cformat, args) - -proc appff(dest: var PRope, cformat, llvmformat: string, - args: varargs[PRope]) = - if gCmd == cmdCompileToLLVM: appf(dest, llvmformat, args) - else: appf(dest, cformat, args) - proc addForwardedProc(m: BModule, prc: PSym) = m.forwardedProcs.add(prc) inc(gForwardedProcsCounter) @@ -137,79 +128,8 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope = if i - 1 >= start: app(result, substr(frmt, start, i - 1)) -const compileTimeRopeFmt = false - -when compileTimeRopeFmt: - import macros - - type TFmtFragmentKind = enum - ffSym, - ffLit, - ffParam - - type TFragment = object - case kind: TFmtFragmentKind - of ffSym, ffLit: - value: string - of ffParam: - intValue: int - - iterator fmtStringFragments(s: string): tuple[kind: TFmtFragmentKind, - value: string, - intValue: int] = - # This is a bit less featured version of the ropecg's algorithm - # (be careful when replacing ropecg calls) - var - i = 0 - length = s.len - - while i < length: - var start = i - case s[i] - of '$': - let n = s[i+1] - case n - of '$': - inc i, 2 - of '0'..'9': - # XXX: use the new case object construction syntax when it's ready - yield (kind: ffParam, value: "", intValue: n.ord - ord('1')) - inc i, 2 - start = i - else: - inc i - of '#': - inc i - var j = i - while s[i] in IdentChars: inc i - yield (kind: ffSym, value: substr(s, j, i-1), intValue: 0) - start = i - else: discard - - while i < length: - if s[i] != '$' and s[i] != '#': inc i - else: break - - if i - 1 >= start: - yield (kind: ffLit, value: substr(s, start, i-1), intValue: 0) - - macro rfmt(m: BModule, fmt: static[string], args: varargs[PRope]): expr = - ## Experimental optimized rope-formatting operator - ## The run-time code it produces will be very fast, but will it speed up - ## the compilation of nimrod itself or will the macro execution time - ## offset the gains? - result = newCall(bindSym"ropeConcat") - for frag in fmtStringFragments(fmt): - case frag.kind - of ffSym: - result.add(newCall(bindSym"cgsym", m, newStrLitNode(frag.value))) - of ffLit: - result.add(newCall(bindSym"~", newStrLitNode(frag.value))) - of ffParam: - result.add(args[frag.intValue]) -else: - template rfmt(m: BModule, fmt: string, args: varargs[PRope]): expr = - ropecg(m, fmt, args) +template rfmt(m: BModule, fmt: string, args: varargs[PRope]): expr = + ropecg(m, fmt, args) proc appcg(m: BModule, c: var PRope, frmt: TFormatStr, args: varargs[PRope]) = @@ -242,24 +162,14 @@ proc lineCg(p: BProc, s: TCProcSection, frmt: TFormatStr, args: varargs[PRope]) = app(p.s(s), indentLine(p, ropecg(p.module, frmt, args))) -when compileTimeRopeFmt: - template linefmt(p: BProc, s: TCProcSection, frmt: TFormatStr, - args: varargs[PRope]) = - line(p, s, rfmt(p.module, frmt, args)) -else: - proc linefmt(p: BProc, s: TCProcSection, frmt: TFormatStr, - args: varargs[PRope]) = - app(p.s(s), indentLine(p, ropecg(p.module, frmt, args))) +proc linefmt(p: BProc, s: TCProcSection, frmt: TFormatStr, + args: varargs[PRope]) = + app(p.s(s), indentLine(p, ropecg(p.module, frmt, args))) proc appLineCg(p: BProc, r: var PRope, frmt: TFormatStr, args: varargs[PRope]) = app(r, indentLine(p, ropecg(p.module, frmt, args))) -proc lineFF(p: BProc, s: TCProcSection, cformat, llvmformat: string, - args: varargs[PRope]) = - if gCmd == cmdCompileToLLVM: lineF(p, s, llvmformat, args) - else: lineF(p, s, cformat, args) - proc safeLineNm(info: TLineInfo): int = result = toLinenumber(info) if result < 0: result = 0 # negative numbers are not allowed in #line @@ -267,8 +177,8 @@ proc safeLineNm(info: TLineInfo): int = proc genCLineDir(r: var PRope, filename: string, line: int) = assert line >= 0 if optLineDir in gOptions: - appff(r, "$N#line $2 $1$N", "; line $2 \"$1\"$n", - [toRope(makeSingleLineCString(filename)), toRope(line)]) + appf(r, "$N#line $2 $1$N", + [toRope(makeSingleLineCString(filename)), toRope(line)]) proc genCLineDir(r: var PRope, info: TLineInfo) = genCLineDir(r, info.toFullPath, info.safeLineNm) @@ -402,11 +312,8 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) = proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) = inc(p.labels) - if gCmd == cmdCompileToLLVM: - result.r = con("%LOC", toRope(p.labels)) - else: - result.r = con("LOC", toRope(p.labels)) - linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r) + result.r = con("LOC", toRope(p.labels)) + linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r) result.k = locTemp #result.a = - 1 result.t = getUniqueType(t) @@ -446,29 +353,6 @@ proc deinitGCFrame(p: BProc): PRope = if p.gcFrameId > 0: result = ropecg(p.module, "if (((NU)&GCFRAME) < 4096) #nimGCFrame(&GCFRAME);$n") - -proc cstringLit(p: BProc, r: var PRope, s: string): PRope = - if gCmd == cmdCompileToLLVM: - inc(p.module.labels) - inc(p.labels) - result = ropef("%LOC$1", [toRope(p.labels)]) - appf(p.module.s[cfsData], "@C$1 = private constant [$2 x i8] $3$n", - [toRope(p.module.labels), toRope(len(s)), makeLLVMString(s)]) - appf(r, "$1 = getelementptr [$2 x i8]* @C$3, %NI 0, %NI 0$n", - [result, toRope(len(s)), toRope(p.module.labels)]) - else: - result = makeCString(s) - -proc cstringLit(m: BModule, r: var PRope, s: string): PRope = - if gCmd == cmdCompileToLLVM: - inc(m.labels, 2) - result = ropef("%MOC$1", [toRope(m.labels - 1)]) - appf(m.s[cfsData], "@MOC$1 = private constant [$2 x i8] $3$n", - [toRope(m.labels), toRope(len(s)), makeLLVMString(s)]) - appf(r, "$1 = getelementptr [$2 x i8]* @MOC$3, %NI 0, %NI 0$n", - [result, toRope(len(s)), toRope(m.labels)]) - else: - result = makeCString(s) proc allocParam(p: BProc, s: PSym) = assert(s.kind == skParam) @@ -494,22 +378,26 @@ proc localDebugInfo(p: BProc, s: PSym) = inc(p.maxFrameLen) inc p.blocks[p.blocks.len-1].frameLen -proc assignLocalVar(p: BProc, s: PSym) = - #assert(s.loc.k == locNone) // not yet assigned - # this need not be fullfilled for inline procs; they are regenerated - # for each module that uses them! +proc localVarDecl(p: BProc; s: PSym): PRope = if s.loc.k == locNone: fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack) if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy) - var decl = getTypeDesc(p.module, s.loc.t) + result = getTypeDesc(p.module, s.loc.t) if s.constraint.isNil: - if sfRegister in s.flags: app(decl, " register") + if sfRegister in s.flags: app(result, " register") #elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds: # app(decl, " GC_GUARD") - if sfVolatile in s.flags: app(decl, " volatile") - appf(decl, " $1;$n", [s.loc.r]) + if sfVolatile in s.flags: app(result, " volatile") + app(result, " ") + app(result, s.loc.r) else: - decl = ropef(s.cgDeclFrmt & ";$n", decl, s.loc.r) + result = ropef(s.cgDeclFrmt, result, s.loc.r) + +proc assignLocalVar(p: BProc, s: PSym) = + #assert(s.loc.k == locNone) # not yet assigned + # this need not be fullfilled for inline procs; they are regenerated + # for each module that uses them! + let decl = localVarDecl(p, s).con(";" & tnl) line(p, cpsLocals, decl) localDebugInfo(p, s) @@ -552,13 +440,11 @@ proc assignGlobalVar(p: BProc, s: PSym) = {optStackTrace, optEndb}: appcg(p.module, p.module.s[cfsDebugInit], "#dbgRegisterGlobal($1, &$2, $3);$n", - [cstringLit(p, p.module.s[cfsDebugInit], - normalize(s.owner.name.s & '.' & s.name.s)), + [makeCString(normalize(s.owner.name.s & '.' & s.name.s)), s.loc.r, genTypeInfo(p.module, s.typ)]) proc assignParam(p: BProc, s: PSym) = assert(s.loc.r != nil) - if sfAddrTaken in s.flags and gCmd == cmdCompileToLLVM: allocParam(p, s) localDebugInfo(p, s) proc fillProcLoc(sym: PSym) = @@ -586,6 +472,11 @@ proc initLocExpr(p: BProc, e: PNode, result: var TLoc) = initLoc(result, locNone, e.typ, OnUnknown) expr(p, e, result) +proc initLocExprSingleUse(p: BProc, e: PNode, result: var TLoc) = + initLoc(result, locNone, e.typ, OnUnknown) + result.flags.incl lfSingleUse + expr(p, e, result) + proc lenField(p: BProc): PRope = result = toRope(if p.module.compileToCpp: "len" else: "Sup.len") @@ -647,7 +538,6 @@ proc symInDynamicLib(m: BModule, sym: PSym) = let isCall = isGetProcAddr(lib) var extname = sym.loc.r if not isCall: loadDynamicLib(m, lib) - if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect) var tmp = mangleDynLibProc(sym) sym.loc.r = tmp # from now on we only need the internal name sym.typ.sym = nil # generate a new name @@ -663,7 +553,7 @@ proc symInDynamicLib(m: BModule, sym: PSym) = params.app(", ") let load = ropef("\t$1 = ($2) ($3$4));$n", [tmp, getTypeDesc(m, sym.typ), - params, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname))]) + params, makeCString(ropeToStr(extname))]) var last = lastSon(n) if last.kind == nkHiddenStdConv: last = last.sons[1] internalAssert(last.kind == nkStrLit) @@ -678,10 +568,8 @@ proc symInDynamicLib(m: BModule, sym: PSym) = appcg(m, m.s[cfsDynLibInit], "\t$1 = ($2) #nimGetProcAddr($3, $4);$n", [tmp, getTypeDesc(m, sym.typ), - lib.name, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname))]) - appff(m.s[cfsVars], "$2 $1;$n", - "$1 = linkonce global $2 zeroinitializer$n", - [sym.loc.r, getTypeDesc(m, sym.loc.t)]) + lib.name, makeCString(ropeToStr(extname))]) + appf(m.s[cfsVars], "$2 $1;$n", [sym.loc.r, getTypeDesc(m, sym.loc.t)]) proc varInDynamicLib(m: BModule, sym: PSym) = var lib = sym.annex @@ -694,7 +582,7 @@ proc varInDynamicLib(m: BModule, sym: PSym) = appcg(m, m.s[cfsDynLibInit], "$1 = ($2*) #nimGetProcAddr($3, $4);$n", [tmp, getTypeDesc(m, sym.typ), - lib.name, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname))]) + lib.name, makeCString(ropeToStr(extname))]) appf(m.s[cfsVars], "$2* $1;$n", [sym.loc.r, getTypeDesc(m, sym.loc.t)]) @@ -717,13 +605,13 @@ proc cgsym(m: BModule, name: string): PRope = rawMessage(errSystemNeeds, name) result = sym.loc.r -proc generateHeaders(m: BModule) = +proc generateHeaders(m: BModule) = app(m.s[cfsHeaders], tnl & "#include \"nimbase.h\"" & tnl) var it = PStrEntry(m.headerFiles.head) - while it != nil: + while it != nil: if it.data[0] notin {'\"', '<'}: appf(m.s[cfsHeaders], "$N#include \"$1\"$N", [toRope(it.data)]) - else: + else: appf(m.s[cfsHeaders], "$N#include $1$N", [toRope(it.data)]) it = PStrEntry(it.next) @@ -796,16 +684,17 @@ proc genProcAux(m: BModule, prc: PSym) = app(generatedProc, initGCFrame(p)) if optStackTrace in prc.options: app(generatedProc, p.s(cpsLocals)) - var procname = cstringLit(p, generatedProc, prc.name.s) + var procname = makeCString(prc.name.s) app(generatedProc, initFrame(p, procname, prc.info.quotedFilename)) else: app(generatedProc, p.s(cpsLocals)) - if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM): + if optProfiler in prc.options: # invoke at proc entry for recursion: appcg(p, cpsInit, "\t#nimProfile();$n", []) + if p.beforeRetNeeded: app(generatedProc, "{") app(generatedProc, p.s(cpsInit)) app(generatedProc, p.s(cpsStmts)) - if p.beforeRetNeeded: app(generatedProc, ~"\tBeforeRet: ;$n") + if p.beforeRetNeeded: app(generatedProc, ~"\t}BeforeRet: ;$n") app(generatedProc, deinitGCFrame(p)) if optStackTrace in prc.options: app(generatedProc, deinitFrame(p)) app(generatedProc, returnStmt) @@ -825,7 +714,6 @@ proc genProcPrototype(m: BModule, sym: PSym) = not containsOrIncl(m.declaredThings, sym.id): app(m.s[cfsVars], rfmt(nil, "extern $1 $2;$n", getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym))) - if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect) elif not containsOrIncl(m.declaredProtos, sym.id): var header = genProcHeader(m, sym) if sym.typ.callConv != ccInline and crossesCppBoundary(m, sym): @@ -923,21 +811,17 @@ proc addIntTypes(result: var PRope) {.inline.} = proc getCopyright(cfile: string): PRope = if optCompileOnly in gGlobalOptions: - result = ropeff("/* Generated by Nim Compiler v$1 */$N" & + result = ropef("/* Generated by Nim Compiler v$1 */$N" & "/* (c) 2015 Andreas Rumpf */$N" & "/* The generated code is subject to the original license. */$N", - "; Generated by Nim Compiler v$1$N" & - "; (c) 2012 Andreas Rumpf$N", [toRope(VersionAsString)]) + [toRope(VersionAsString)]) else: - result = ropeff("/* Generated by Nim Compiler v$1 */$N" & + result = ropef("/* Generated by Nim Compiler v$1 */$N" & "/* (c) 2015 Andreas Rumpf */$N" & "/* The generated code is subject to the original license. */$N" & "/* Compiled for: $2, $3, $4 */$N" & "/* Command for C compiler:$n $5 */$N", - "; Generated by Nim Compiler v$1$N" & - "; (c) 2015 Andreas Rumpf$N" & - "; Compiled for: $2, $3, $4$N" & - "; Command for LLVM compiler:$N $5$N", [toRope(VersionAsString), + [toRope(VersionAsString), toRope(platform.OS[targetOS].name), toRope(platform.CPU[targetCPU].name), toRope(extccomp.CC[extccomp.cCompiler].name), @@ -1088,13 +972,11 @@ proc registerModuleToMain(m: PSym) = var init = m.getInitName datInit = m.getDatInitName - appff(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", - "declare void $1() noinline$N", [init]) - appff(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", - "declare void $1() noinline$N", [datInit]) + appf(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", [init]) + appf(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", [datInit]) if sfSystemModule notin m.flags: - appff(mainDatInit, "\t$1();$N", "call void ()* $1$n", [datInit]) - let initCall = ropeff("\t$1();$N", "call void ()* $1$n", [init]) + appf(mainDatInit, "\t$1();$N", [datInit]) + let initCall = ropef("\t$1();$N", [init]) if sfMainModule in m.flags: app(mainModInit, initCall) else: @@ -1102,8 +984,7 @@ proc registerModuleToMain(m: PSym) = proc genInitCode(m: BModule) = var initname = getInitName(m.module) - var prc = ropeff("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N", - "define void $1() noinline {$n", [initname]) + var prc = ropef("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N", [initname]) if m.typeNodes > 0: appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n", [m.typeNodesName, toRope(m.typeNodes)]) @@ -1124,7 +1005,7 @@ proc genInitCode(m: BModule) = # declare it nevertheless: m.frameDeclared = true if not m.preventStackTrace: - var procname = cstringLit(m.initProc, prc, m.module.name.s) + var procname = makeCString(m.module.name.s) app(prc, initFrame(m.initProc, procname, m.module.info.quotedFilename)) else: app(prc, ~"\tTFrame F; F.len = 0;$N") @@ -1145,8 +1026,8 @@ proc genInitCode(m: BModule) = app(prc, deinitGCFrame(m.initProc)) appf(prc, "}$N$N") - prc.appff("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N", - "define void $1() noinline {$n", [getDatInitName(m.module)]) + prc.appf("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N", + [getDatInitName(m.module)]) for i in cfsTypeInit1..cfsDynLibInit: app(prc, genSectionStart(i)) diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index 508f98074..bb98454a7 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -82,6 +82,9 @@ type maxFrameLen*: int # max length of frame descriptor module*: BModule # used to prevent excessive parameter passing withinLoop*: int # > 0 if we are within a loop + splitDecls*: int # > 0 if we are in some context for C++ that + # requires 'T x = T()' to become 'T x; x = T()' + # (yes, C++ is weird like that) gcFrameId*: Natural # for the GC stack marking gcFrameType*: PRope # the struct {} we put the GC markers into diff --git a/compiler/commands.nim b/compiler/commands.nim index 78fa9249c..c81b81d19 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -52,7 +52,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) const HelpMessage = "Nim Compiler Version $1 (" & CompileDate & ") [$2: $3]\n" & - "Copyright (c) 2006-2014 by Andreas Rumpf\n" + "Copyright (c) 2006-2015 by Andreas Rumpf\n" const Usage = slurp"doc/basicopt.txt".replace("//", "") diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index bc888315f..8e40cca39 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -428,13 +428,17 @@ proc addFileToLink*(filename: string) = prependStr(toLink, filename) # BUGFIX: was ``appendStr`` -proc execExternalProgram*(cmd: string, prettyCmd = "") = +proc execWithEcho(cmd: string, prettyCmd = ""): int = if optListCmd in gGlobalOptions or gVerbosity > 0: if prettyCmd != "": msgWriteln(prettyCmd) else: msgWriteln(cmd) - if execCmd(cmd) != 0: rawMessage(errExecutionOfProgramFailed, "") + result = execCmd(cmd) + +proc execExternalProgram*(cmd: string, prettyCmd = "") = + if execWithEcho(cmd, prettyCmd) != 0: + rawMessage(errExecutionOfProgramFailed, "") proc generateScript(projectFile: string, script: PRope) = let (dir, name, ext) = splitFile(projectFile) @@ -622,7 +626,7 @@ proc callCCompiler*(projectfile: string) = if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors() var res = 0 if gNumberOfProcessors <= 1: - for i in countup(0, high(cmds)): res = max(execCmd(cmds[i]), res) + for i in countup(0, high(cmds)): res = max(execWithEcho(cmds[i]), res) elif optListCmd in gGlobalOptions or gVerbosity > 1: res = execProcesses(cmds, {poEchoCmd, poUseShell, poParentStreams}, gNumberOfProcessors) diff --git a/compiler/llstream.nim b/compiler/llstream.nim index be469548d..69475965d 100644 --- a/compiler/llstream.nim +++ b/compiler/llstream.nim @@ -30,47 +30,32 @@ type PLLStream* = ref TLLStream -proc llStreamOpen*(data: string): PLLStream -proc llStreamOpen*(f: var File): PLLStream -proc llStreamOpen*(filename: string, mode: FileMode): PLLStream -proc llStreamOpen*(): PLLStream -proc llStreamOpenStdIn*(): PLLStream -proc llStreamClose*(s: PLLStream) -proc llStreamRead*(s: PLLStream, buf: pointer, bufLen: int): int -proc llStreamReadLine*(s: PLLStream, line: var string): bool -proc llStreamReadAll*(s: PLLStream): string -proc llStreamWrite*(s: PLLStream, data: string) -proc llStreamWrite*(s: PLLStream, data: char) -proc llStreamWrite*(s: PLLStream, buf: pointer, buflen: int) -proc llStreamWriteln*(s: PLLStream, data: string) -# implementation - -proc llStreamOpen(data: string): PLLStream = +proc llStreamOpen*(data: string): PLLStream = new(result) result.s = data result.kind = llsString -proc llStreamOpen(f: var File): PLLStream = +proc llStreamOpen*(f: var File): PLLStream = new(result) result.f = f result.kind = llsFile -proc llStreamOpen(filename: string, mode: FileMode): PLLStream = +proc llStreamOpen*(filename: string, mode: FileMode): PLLStream = new(result) result.kind = llsFile if not open(result.f, filename, mode): result = nil -proc llStreamOpen(): PLLStream = +proc llStreamOpen*(): PLLStream = new(result) result.kind = llsNone -proc llStreamOpenStdIn(): PLLStream = +proc llStreamOpenStdIn*(): PLLStream = new(result) result.kind = llsStdIn result.s = "" result.lineOffset = -1 -proc llStreamClose(s: PLLStream) = +proc llStreamClose*(s: PLLStream) = case s.kind of llsNone, llsString, llsStdIn: discard @@ -130,7 +115,7 @@ proc llReadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int = copyMem(buf, addr(s.s[s.rd]), result) inc(s.rd, result) -proc llStreamRead(s: PLLStream, buf: pointer, bufLen: int): int = +proc llStreamRead*(s: PLLStream, buf: pointer, bufLen: int): int = case s.kind of llsNone: result = 0 @@ -144,7 +129,7 @@ proc llStreamRead(s: PLLStream, buf: pointer, bufLen: int): int = of llsStdIn: result = llReadFromStdin(s, buf, bufLen) -proc llStreamReadLine(s: PLLStream, line: var string): bool = +proc llStreamReadLine*(s: PLLStream, line: var string): bool = setLen(line, 0) case s.kind of llsNone: @@ -168,7 +153,7 @@ proc llStreamReadLine(s: PLLStream, line: var string): bool = of llsStdIn: result = readLine(stdin, line) -proc llStreamWrite(s: PLLStream, data: string) = +proc llStreamWrite*(s: PLLStream, data: string) = case s.kind of llsNone, llsStdIn: discard @@ -178,11 +163,11 @@ proc llStreamWrite(s: PLLStream, data: string) = of llsFile: write(s.f, data) -proc llStreamWriteln(s: PLLStream, data: string) = +proc llStreamWriteln*(s: PLLStream, data: string) = llStreamWrite(s, data) llStreamWrite(s, "\n") -proc llStreamWrite(s: PLLStream, data: char) = +proc llStreamWrite*(s: PLLStream, data: char) = var c: char case s.kind of llsNone, llsStdIn: @@ -194,7 +179,7 @@ proc llStreamWrite(s: PLLStream, data: char) = c = data discard writeBuffer(s.f, addr(c), sizeof(c)) -proc llStreamWrite(s: PLLStream, buf: pointer, buflen: int) = +proc llStreamWrite*(s: PLLStream, buf: pointer, buflen: int) = case s.kind of llsNone, llsStdIn: discard @@ -206,7 +191,7 @@ proc llStreamWrite(s: PLLStream, buf: pointer, buflen: int) = of llsFile: discard writeBuffer(s.f, buf, buflen) -proc llStreamReadAll(s: PLLStream): string = +proc llStreamReadAll*(s: PLLStream): string = const bufSize = 2048 case s.kind diff --git a/compiler/main.nim b/compiler/main.nim index 06dcad7b0..42a782c02 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -251,7 +251,6 @@ proc mainCommand* = commandCompileToC() of "cpp", "compiletocpp": gCmd = cmdCompileToCpp - if cCompiler == ccGcc: setCC("gcc") defineSymbol("cpp") commandCompileToC() of "objc", "compiletooc": diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 35a121769..be69f1ea5 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -113,7 +113,7 @@ type warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel, warnUnknownSubstitutionX, warnLanguageXNotSupported, warnFieldXNotSupported, warnCommentXIgnored, - warnNilStatement, warnAnalysisLoophole, + warnNilStatement, warnTypelessParam, warnDifferentHeaps, warnWriteToForeignHeap, warnUnsafeCode, warnEachIdentIsTuple, warnShadowIdent, warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2, @@ -311,7 +311,7 @@ const errXOnlyAtModuleScope: "\'$1\' is only allowed at top level", errXNeedsParamObjectType: "'$1' needs a parameter that has an object type", errTemplateInstantiationTooNested: "template/macro instantiation too nested", - errInstantiationFrom: "instantiation from here", + errInstantiationFrom: "template/generic instantiation from here", errInvalidIndexValueForTuple: "invalid index value for tuple subscript", errCommandExpectsFilename: "command expects a filename argument", errMainModuleMustBeSpecified: "please, specify a main module in the project configuration file", @@ -376,7 +376,7 @@ const warnFieldXNotSupported: "field \'$1\' not supported [FieldXNotSupported]", warnCommentXIgnored: "comment \'$1\' ignored [CommentXIgnored]", warnNilStatement: "'nil' statement is deprecated; use an empty 'discard' statement instead [NilStmt]", - warnAnalysisLoophole: "thread analysis incomplete due to unknown call '$1' [AnalysisLoophole]", + warnTypelessParam: "'$1' has no type. Typeless parameters are deprecated; only allowed for 'template' [TypelessParam]", warnDifferentHeaps: "possible inconsistency of thread local heaps [DifferentHeaps]", warnWriteToForeignHeap: "write to foreign heap [WriteToForeignHeap]", warnUnsafeCode: "unsafe code: '$1' [UnsafeCode]", @@ -418,7 +418,7 @@ const "RedefinitionOfLabel", "UnknownSubstitutionX", "LanguageXNotSupported", "FieldXNotSupported", "CommentXIgnored", "NilStmt", - "AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap", + "TypelessParam", "DifferentHeaps", "WriteToForeignHeap", "UnsafeCode", "EachIdentIsTuple", "ShadowIdent", "ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit", "GcMem", "Destructor", "LockLevel", "User"] @@ -460,7 +460,7 @@ type TLineInfo*{.final.} = object # This is designed to be as small as possible, # because it is used - # in syntax nodes. We safe space here by using + # in syntax nodes. We save space here by using # two int16 and an int32. # On 64 bit and on 32 bit systems this is # only 8 bytes. @@ -522,7 +522,7 @@ proc newFileInfo(fullPath, projPath: string): TFileInfo = if optEmbedOrigSrc in gGlobalOptions or true: result.lines = @[] -proc fileInfoIdx*(filename: string): int32 = +proc fileInfoIdx*(filename: string; isKnownFile: var bool): int32 = var canon: string pseudoPath = false @@ -539,11 +539,16 @@ proc fileInfoIdx*(filename: string): int32 = if filenameToIndexTbl.hasKey(canon): result = filenameToIndexTbl[canon] else: + isKnownFile = false result = fileInfos.len.int32 fileInfos.add(newFileInfo(canon, if pseudoPath: filename else: canon.shortenDir)) filenameToIndexTbl[canon] = result +proc fileInfoIdx*(filename: string): int32 = + var dummy: bool + result = fileInfoIdx(filename, dummy) + proc newLineInfo*(fileInfoIdx: int32, line, col: int): TLineInfo = result.fileIndex = fileInfoIdx result.line = int16(line) diff --git a/compiler/nim.nimrod.cfg b/compiler/nim.nim.cfg index f4d8b9dcb..f4d8b9dcb 100644 --- a/compiler/nim.nimrod.cfg +++ b/compiler/nim.nim.cfg diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim index bcf9b5359..711b476e6 100644 --- a/compiler/nimconf.nim +++ b/compiler/nimconf.nim @@ -11,10 +11,10 @@ import llstream, nversion, commands, os, strutils, msgs, platform, condsyms, lexer, - options, idents, wordrecg + options, idents, wordrecg, strtabs # ---------------- configuration file parser ----------------------------- -# we use Nim's scanner here to safe space and work +# we use Nim's scanner here to save space and work proc ppGetTok(L: var TLexer, tok: var TToken) = # simple filter @@ -82,17 +82,17 @@ proc doElif(L: var TLexer, tok: var TToken) = proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest) = var nestedIfs = 0 while true: - if (tok.ident != nil) and (tok.ident.s == "@"): + if tok.ident != nil and tok.ident.s == "@": ppGetTok(L, tok) case whichKeyword(tok.ident) of wIf: inc(nestedIfs) of wElse: - if (dest == jdElseEndif) and (nestedIfs == 0): + if dest == jdElseEndif and nestedIfs == 0: doElse(L, tok) break of wElif: - if (dest == jdElseEndif) and (nestedIfs == 0): + if dest == jdElseEndif and nestedIfs == 0: doElif(L, tok) break of wEnd: @@ -119,9 +119,10 @@ proc parseDirective(L: var TLexer, tok: var TToken) = of wElif: doElif(L, tok) of wElse: doElse(L, tok) of wEnd: doEnd(L, tok) - of wWrite: + of wWrite: ppGetTok(L, tok) - msgs.msgWriteln(tokToStr(tok)) + msgs.msgWriteln(strtabs.`%`(tokToStr(tok), options.gConfigVars, + {useEnvironment, useKey})) ppGetTok(L, tok) else: case tok.ident.s.normalize @@ -157,7 +158,7 @@ proc checkSymbol(L: TLexer, tok: TToken) = proc parseAssignment(L: var TLexer, tok: var TToken) = if tok.ident.id == getIdent("-").id or tok.ident.id == getIdent("--").id: confTok(L, tok) # skip unnecessary prefix - var info = getLineInfo(L, tok) # safe for later in case of an error + var info = getLineInfo(L, tok) # save for later in case of an error checkSymbol(L, tok) var s = tokToStr(tok) confTok(L, tok) # skip symbol @@ -178,9 +179,10 @@ proc parseAssignment(L: var TLexer, tok: var TToken) = if tok.tokType == tkBracketRi: confTok(L, tok) else: lexMessage(L, errTokenExpected, "']'") add(val, ']') - if tok.tokType in {tkColon, tkEquals}: + let percent = tok.ident.id == getIdent("%=").id + if tok.tokType in {tkColon, tkEquals} or percent: if len(val) > 0: add(val, ':') - confTok(L, tok) # skip ':' or '=' + confTok(L, tok) # skip ':' or '=' or '%' checkSymbol(L, tok) add(val, tokToStr(tok)) confTok(L, tok) # skip symbol @@ -189,7 +191,11 @@ proc parseAssignment(L: var TLexer, tok: var TToken) = checkSymbol(L, tok) add(val, tokToStr(tok)) confTok(L, tok) - processSwitch(s, val, passPP, info) + if percent: + processSwitch(s, strtabs.`%`(val, options.gConfigVars, + {useEnvironment, useEmpty}), passPP, info) + else: + processSwitch(s, val, passPP, info) proc readConfigFile(filename: string) = var @@ -246,6 +252,11 @@ proc loadConfigs*(cfg: string) = if gProjectName.len != 0: # new project wide config file: - let projectConfig = changeFileExt(gProjectFull, "nim.cfg") - if fileExists(projectConfig): readConfigFile(projectConfig) - else: readConfigFile(changeFileExt(gProjectFull, "nimrod.cfg")) + var projectConfig = changeFileExt(gProjectFull, "nimcfg") + if not fileExists(projectConfig): + projectConfig = changeFileExt(gProjectFull, "nim.cfg") + if not fileExists(projectConfig): + projectConfig = changeFileExt(gProjectFull, "nimrod.cfg") + if fileExists(projectConfig): + rawMessage(warnDeprecated, projectConfig) + readConfigFile(projectConfig) diff --git a/compiler/nimsuggest/nimsuggest.nim b/compiler/nimsuggest/nimsuggest.nim index 6edea06e5..cac078127 100644 --- a/compiler/nimsuggest/nimsuggest.nim +++ b/compiler/nimsuggest/nimsuggest.nim @@ -87,8 +87,9 @@ proc action(cmd: string) = i += skipWhile(cmd, seps, i) i += parseInt(cmd, col, i) + var isKnownFile = true if orig.len == 0: err() - let dirtyIdx = orig.fileInfoIdx + let dirtyIdx = orig.fileInfoIdx(isKnownFile) if dirtyfile.len != 0: msgs.setDirtyFile(dirtyIdx, dirtyfile) else: msgs.setDirtyFile(dirtyIdx, nil) @@ -99,7 +100,10 @@ proc action(cmd: string) = gTrackPos = newLineInfo(dirtyIdx, line, col) #echo dirtyfile, gDirtyBufferIdx, " project ", gProjectMainIdx gErrorCounter = 0 - compileProject() + if not isKnownFile: + compileProject(dirtyIdx) + else: + compileProject() proc serve() = # do not stop after the first error: diff --git a/compiler/parser.nim b/compiler/parser.nim index aae0ce7f9..f249b37c8 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -198,8 +198,8 @@ proc isSigilLike(tok: TToken): bool {.inline.} = proc isRightAssociative(tok: TToken): bool {.inline.} = ## Determines whether the token is right assocative. - result = tok.tokType == tkOpr and (tok.ident.s[0] == '^' or - (let L = tok.ident.s.len; L > 1 and tok.ident.s[L-1] == '>')) + result = tok.tokType == tkOpr and tok.ident.s[0] == '^' + # or (let L = tok.ident.s.len; L > 1 and tok.ident.s[L-1] == '>')) proc getPrecedence(tok: TToken, strongSpaces: bool): int = ## Calculates the precedence of the given token. diff --git a/compiler/platform.nim b/compiler/platform.nim index 8360a9dcc..a21e73248 100644 --- a/compiler/platform.nim +++ b/compiler/platform.nim @@ -138,7 +138,7 @@ const props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}), (name: "VxWorks", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/", objExt: ".o", newLine: "\x0A", pathSep: ";", dirSep: "\\", - scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".", + scriptExt: ".sh", curDir: ".", exeExt: ".vxe", extSep: ".", props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}), (name: "JS", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/", diff --git a/compiler/semcall.nim b/compiler/semcall.nim index cdfdfc9d0..5cb713030 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -315,6 +315,8 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode, var r = resolveOverloads(c, n, nOrig, filter, errors) if r.state == csMatch: result = semResolvedCall(c, n, r) else: + # get rid of the deref again for a better error message: + n.sons[1] = n.sons[1].sons[0] notFoundError(c, n, errors) else: notFoundError(c, n, errors) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index cd27cf15d..40413e3eb 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -103,28 +103,31 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = result = newSymNode(s, n.info) of skMacro: result = semMacroExpr(c, n, n, s, flags) of skTemplate: result = semTemplateExpr(c, n, s, flags) - of skVar, skLet, skResult, skParam, skForVar: + of skParam: + markUsed(n.info, s) + styleCheckUse(n.info, s) + if s.typ.kind == tyStatic and s.typ.n != nil: + # XXX see the hack in sigmatch.nim ... + return s.typ.n + elif sfGenSym in s.flags: + if c.p.wasForwarded: + # gensym'ed parameters that nevertheless have been forward declared + # need a special fixup: + let realParam = c.p.owner.typ.n[s.position+1] + internalAssert realParam.kind == nkSym and realParam.sym.kind == skParam + return newSymNode(c.p.owner.typ.n[s.position+1].sym, n.info) + elif c.p.owner.kind == skMacro: + # gensym'ed macro parameters need a similar hack (see bug #1944): + var u = searchInScopes(c, s.name) + internalAssert u != nil and u.kind == skParam and u.owner == s.owner + return newSymNode(u, n.info) + result = newSymNode(s, n.info) + of skVar, skLet, skResult, skForVar: markUsed(n.info, s) styleCheckUse(n.info, s) # if a proc accesses a global variable, it is not side effect free: if sfGlobal in s.flags: incl(c.p.owner.flags, sfSideEffect) - elif s.kind == skParam: - if s.typ.kind == tyStatic and s.typ.n != nil: - # XXX see the hack in sigmatch.nim ... - return s.typ.n - elif sfGenSym in s.flags: - if c.p.wasForwarded: - # gensym'ed parameters that nevertheless have been forward declared - # need a special fixup: - let realParam = c.p.owner.typ.n[s.position+1] - internalAssert realParam.kind == nkSym and realParam.sym.kind == skParam - return newSymNode(c.p.owner.typ.n[s.position+1].sym, n.info) - elif c.p.owner.kind == skMacro: - # gensym'ed macro parameters need a similar hack (see bug #1944): - var u = searchInScopes(c, s.name) - internalAssert u != nil and u.kind == skParam and u.owner == s.owner - return newSymNode(u, n.info) result = newSymNode(s, n.info) # We cannot check for access to outer vars for example because it's still # not sure the symbol really ends up being used: @@ -306,7 +309,7 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = var typ = skipTypes(n.sons[1].typ, abstractVarRange + {tyTypeDesc, tyFieldAccessor}) case typ.kind - of tySequence, tyString, tyOpenArray, tyVarargs: + of tySequence, tyString, tyCString, tyOpenArray, tyVarargs: n.typ = getSysType(tyInt) of tyArrayConstr, tyArray: n.typ = typ.sons[0] # indextype @@ -578,11 +581,12 @@ proc skipObjConv(n: PNode): PNode = proc isAssignable(c: PContext, n: PNode): TAssignableResult = result = parampatterns.isAssignable(c.p.owner, n) -proc newHiddenAddrTaken(c: PContext, n: PNode): PNode = - if n.kind == nkHiddenDeref: +proc newHiddenAddrTaken(c: PContext, n: PNode): PNode = + if n.kind == nkHiddenDeref and not (gCmd == cmdCompileToCpp or + sfCompileToCpp in c.module.flags): checkSonsLen(n, 1) result = n.sons[0] - else: + else: result = newNodeIT(nkHiddenAddr, n.info, makeVarType(c, n.typ)) addSon(result, n) if isAssignable(c, n) notin {arLValue, arLocalLValue}: @@ -1209,6 +1213,7 @@ proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} = if x.typ.kind == tyVar and x.kind == nkSym and x.sym.kind == skResult: n.sons[0] = x # 'result[]' --> 'result' n.sons[1] = takeImplicitAddr(c, ri) + x.typ.flags.incl tfVarIsPtr template resultTypeIsInferrable(typ: PType): expr = typ.isMetaType and typ.kind != tyTypeDesc @@ -2113,7 +2118,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = of nkCurly: result = semSetConstr(c, n) of nkBracket: result = semArrayConstr(c, n, flags) of nkObjConstr: result = semObjConstr(c, n, flags) - of nkLambdaKinds: result = semLambda(c, n, flags) + of nkLambda: result = semLambda(c, n, flags) + of nkDo: result = semDo(c, n, flags) of nkDerefExpr: result = semDeref(c, n) of nkAddr: result = n diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 1988c512e..a3f1b1c13 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -665,8 +665,8 @@ proc getConstExpr(m: PSym, n: PNode): PNode = of mLow: result = newIntNodeT(firstOrd(n.sons[1].typ), n) of mHigh: - if skipTypes(n.sons[1].typ, abstractVar).kind notin - {tyOpenArray, tyVarargs, tySequence, tyString}: + if skipTypes(n.sons[1].typ, abstractVar).kind notin + {tySequence, tyString, tyCString, tyOpenArray, tyVarargs}: result = newIntNodeT(lastOrd(skipTypes(n[1].typ, abstractVar)), n) else: var a = getArrayConstr(m, n.sons[1]) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 81a4465c5..e02d6d1e5 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -77,11 +77,16 @@ proc removeDefaultParamValues(n: PNode) = proc freshGenSyms(n: PNode, owner: PSym, symMap: var TIdTable) = # we need to create a fresh set of gensym'ed symbols: if n.kind == nkSym and sfGenSym in n.sym.flags: - var x = PSym(idTableGet(symMap, n.sym)) + let s = n.sym + var x = PSym(idTableGet(symMap, s)) if x == nil: - x = copySym(n.sym, false) - x.owner = owner - idTablePut(symMap, n.sym, x) + if s.kind == skParam: + x = owner.typ.n[s.position+1].sym + internalAssert x.kind == skParam + else: + x = copySym(s, false) + x.owner = owner + idTablePut(symMap, s, x) n.sym = x else: for i in 0 .. <safeLen(n): freshGenSyms(n.sons[i], owner, symMap) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index dcebf86ac..ede556a70 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -230,7 +230,7 @@ proc getEbase(): PType = proc excType(n: PNode): PType = # reraise is like raising E_Base: - let t = if n.kind == nkEmpty: getEbase() else: n.typ + let t = if n.kind == nkEmpty or n.typ.isNil: getEbase() else: n.typ result = skipTypes(t, skipPtrs) proc createRaise(n: PNode): PNode = diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 3fe3e40f0..6e5b272de 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -813,8 +813,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = # we have a list of implicit type parameters: n.sons[genericParamsPos] = gp else: - s.typ = newTypeS(tyProc, c) - rawAddSon(s.typ, nil) + s.typ = newProcType(c, n.info) if n.sons[pragmasPos].kind != nkEmpty: pragma(c, s, n.sons[pragmasPos], lambdaPragmas) s.options = gOptions @@ -826,9 +825,9 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = if gp.len == 0 or (gp.len == 1 and tfRetType in gp[0].typ.flags): pushProcCon(c, s) addResult(c, s.typ.sons[0], n.info, skProc) + addResultNode(c, n) let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos])) n.sons[bodyPos] = transformBody(c.module, semBody, s) - addResultNode(c, n) popProcCon(c) elif efOperand notin flags: localError(n.info, errGenericLambdaNotAllowed) @@ -839,6 +838,13 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = popOwner() result.typ = s.typ +proc semDo(c: PContext, n: PNode, flags: TExprFlags): PNode = + # 'do' without params produces a stmt: + if n[genericParamsPos].kind == nkEmpty and n[paramsPos].kind == nkEmpty: + result = semStmt(c, n[bodyPos]) + else: + result = semLambda(c, n, flags) + proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode = var n = n @@ -854,9 +860,9 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode = addParams(c, n.typ.n, skProc) pushProcCon(c, s) addResult(c, n.typ.sons[0], n.info, skProc) + addResultNode(c, n) let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos])) n.sons[bodyPos] = transformBody(c.module, semBody, n.sons[namePos].sym) - addResultNode(c, n) popProcCon(c) popOwner() closeScope(c) @@ -988,8 +994,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, # check for semantics again: # semParamList(c, n.sons[ParamsPos], nil, s) else: - s.typ = newTypeS(tyProc, c) - rawAddSon(s.typ, nil) + s.typ = newProcType(c, n.info) if n.sons[patternPos].kind != nkEmpty: n.sons[patternPos] = semPattern(c, n.sons[patternPos]) if s.kind in skIterators: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 8d1655593..d052700b2 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -856,25 +856,25 @@ proc semParamType(c: PContext, n: PNode, constraint: var PNode): PType = else: result = semTypeNode(c, n, nil) +proc newProcType(c: PContext; info: TLineInfo; prev: PType = nil): PType = + result = newOrPrevType(tyProc, prev, c) + result.callConv = lastOptionEntry(c).defaultCC + result.n = newNodeI(nkFormalParams, info) + rawAddSon(result, nil) # return type + # result.n[0] used to be `nkType`, but now it's `nkEffectList` because + # the effects are now stored in there too ... this is a bit hacky, but as + # usual we desperately try to save memory: + addSon(result.n, newNodeI(nkEffectList, info)) + proc semProcTypeNode(c: PContext, n, genericParams: PNode, prev: PType, kind: TSymKind; isType=false): PType = # for historical reasons (code grows) this is invoked for parameter # lists too and then 'isType' is false. - var - res: PNode - cl: IntSet + var cl: IntSet checkMinSonsLen(n, 1) - result = newOrPrevType(tyProc, prev, c) - result.callConv = lastOptionEntry(c).defaultCC - result.n = newNodeI(nkFormalParams, n.info) + result = newProcType(c, n.info, prev) if genericParams != nil and sonsLen(genericParams) == 0: cl = initIntSet() - rawAddSon(result, nil) # return type - # result.n[0] used to be `nkType`, but now it's `nkEffectList` because - # the effects are now stored in there too ... this is a bit hacky, but as - # usual we desperately try to save memory: - res = newNodeI(nkEffectList, n.info) - addSon(result.n, res) var check = initIntSet() var counter = 0 for i in countup(1, n.len - 1): @@ -911,6 +911,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, if not hasType and not hasDefault: if isType: localError(a.info, "':' expected") let tdef = if kind in {skTemplate, skMacro}: tyExpr else: tyAnything + if tdef == tyAnything: + message(a.info, warnTypelessParam, renderTree(n)) typ = newTypeS(tdef, c) if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue @@ -956,7 +958,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, # we don't need to change the return type to iter[T] if not r.isInlineIterator: r = newTypeWithSons(c, tyIter, @[r]) result.sons[0] = r - res.typ = r + result.n.typ = r if genericParams != nil: for n in genericParams: diff --git a/compiler/transf.nim b/compiler/transf.nim index f511ed69f..cf13630fd 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -321,6 +321,7 @@ proc transformYield(c: PTransf, n: PNode): PTransNode = proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode = result = transformSons(c, n) + if gCmd == cmdCompileToCpp or sfCompileToCpp in c.module.flags: return var n = result.PNode case n.sons[0].kind of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64: diff --git a/compiler/treetab.nim b/compiler/treetab.nim index 63f3fc6e2..8d66d56c7 100644 --- a/compiler/treetab.nim +++ b/compiler/treetab.nim @@ -28,8 +28,9 @@ proc hashTree(n: PNode): THash = of nkFloatLit..nkFloat64Lit: if (n.floatVal >= - 1000000.0) and (n.floatVal <= 1000000.0): result = result !& toInt(n.floatVal) - of nkStrLit..nkTripleStrLit: - result = result !& hash(n.strVal) + of nkStrLit..nkTripleStrLit: + if not n.strVal.isNil: + result = result !& hash(n.strVal) else: for i in countup(0, sonsLen(n) - 1): result = result !& hashTree(n.sons[i]) diff --git a/compiler/types.nim b/compiler/types.nim index 78d390f13..3711a9668 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1029,16 +1029,18 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, proc typeAllowedNode(marker: var IntSet, n: PNode, kind: TSymKind, flags: TTypeAllowedFlags = {}): PType = - if n != nil: + if n != nil: result = typeAllowedAux(marker, n.typ, kind, flags) #if not result: debug(n.typ) if result == nil: case n.kind - of nkNone..nkNilLit: + of nkNone..nkNilLit: discard else: for i in countup(0, sonsLen(n) - 1): - result = typeAllowedNode(marker, n.sons[i], kind, flags) + let it = n.sons[i] + if it.kind == nkRecCase and kind == skConst: return n.typ + result = typeAllowedNode(marker, it, kind, flags) if result != nil: break proc matchType*(a: PType, pattern: openArray[tuple[k:TTypeKind, i:int]], @@ -1118,7 +1120,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind, result = typeAllowedAux(marker, t.sons[i], kind, flags) if result != nil: break of tyObject, tyTuple: - if kind == skConst and t.kind == tyObject: return t + if kind == skConst and t.kind == tyObject and t.sons[0] != nil: return t let flags = flags+{taField} for i in countup(0, sonsLen(t) - 1): result = typeAllowedAux(marker, t.sons[i], kind, flags) diff --git a/compiler/vm.nim b/compiler/vm.nim index b682b4e25..090498f10 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1438,7 +1438,9 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode = # immediate macros can bypass any type and arity checking so we check the # arity here too: if sym.typ.len > n.safeLen and sym.typ.len > 1: - globalError(n.info, "got $#, but expected $# argument(s)" % [$ <n.safeLen, $ <sym.typ.len]) + globalError(n.info, "in call '$#' got $#, but expected $# argument(s)" % [ + n.renderTree, + $ <n.safeLen, $ <sym.typ.len]) setupGlobalCtx(module) var c = globalCtx diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 120120879..70f81bc72 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -604,7 +604,8 @@ proc genNarrowU(c: PCtx; n: PNode; dest: TDest) = let t = skipTypes(n.typ, abstractVar-{tyTypeDesc}) # uint is uint64 in the VM, we we only need to mask the result for # other unsigned types: - if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32}: + if t.kind in {tyUInt8..tyUInt32, tyInt8..tyInt32} or + (t.kind == tyInt and t.size == 4): c.gABC(n, opcNarrowU, dest, TRegister(t.size*8)) proc genBinaryABCnarrow(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) = @@ -893,7 +894,8 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) = of mHigh: if dest < 0: dest = c.getTemp(n.typ) let tmp = c.genx(n.sons[1]) - if n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).kind == tyString: + case n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).kind: + of tyString, tyCString: c.gABI(n, opcLenStr, dest, tmp, 1) else: c.gABI(n, opcLenSeq, dest, tmp, 1) diff --git a/config/nim.cfg b/config/nim.cfg index 54c77e573..8f5d7e8e7 100644 --- a/config/nim.cfg +++ b/config/nim.cfg @@ -5,7 +5,8 @@ # You may set environment variables with # @putenv "key" "val" -# Environment variables cannot be used in the options, however! +# Environment variables can be accessed like so: +# gcc.path %= "$CC_PATH" cc = gcc @@ -21,6 +22,7 @@ mips.linux.gcc.linkerexe = "mips-openwrt-linux-gcc" @end path="$lib/core" + path="$lib/pure" path="$lib/pure/collections" path="$lib/pure/concurrency" @@ -110,6 +112,20 @@ hint[LineTooLong]=off gcc.cpp.options.always = "-w -fpermissive" @end +# Configuration for the VxWorks +# This has been tested with VxWorks 6.9 only +@if vxworks: + # For now we only support compiling RTPs applications (i.e. no DKMs) + gcc.options.always = "-mrtp -fno-strict-aliasing -D_C99 -D_HAS_C9X -std=c99 -fasm -Wall -Wno-write-strings" + # The linker config must add the VxWorks common library for the selected + # processor which is usually found in: + # "$WIND_BASE/target/lib/usr/lib/PROCESSOR_FAMILY/PROCESSOR_TYPE/common", + # where PROCESSOR_FAMILY and PROCESSOR_TYPE are those supported by the VxWorks + # compiler (e.g. ppc/PPC32 or mips/MIPSI64, etc) + # For now we only support the PowerPC CPU + gcc.options.linker %= "-L $WIND_BASE/target/lib/usr/lib/ppc/PPC32/common -mrtp -fno-strict-aliasing -D_C99 -D_HAS_C9X -std=c99 -fasm -Wall -Wno-write-strings" +@end + gcc.options.speed = "-O3 -fno-strict-aliasing" gcc.options.size = "-Os" gcc.options.debug = "-g3 -O0" diff --git a/doc/advopt.txt b/doc/advopt.txt index 78c3d571a..ae474afc6 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -66,7 +66,6 @@ Advanced options: --threadanalysis:on|off turn thread analysis on|off --tlsEmulation:on|off turn thread local storage emulation on|off --taintMode:on|off turn taint mode on|off - --symbolFiles:on|off turn symbol files on|off (experimental) --implicitStatic:on|off turn implicit compile time evaluation on|off --patterns:on|off turn pattern matching on|off --skipCfg do not read the general configuration file diff --git a/doc/basicopt.txt b/doc/basicopt.txt index e366b2718..27b10badc 100644 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -14,7 +14,6 @@ Options: -p, --path:PATH add path to search paths -d, --define:SYMBOL define a conditional symbol -u, --undef:SYMBOL undefine a conditional symbol - --symbol:SYMBOL declare a conditional symbol -f, --forceBuild force rebuilding of all modules --stackTrace:on|off turn stack tracing on|off --lineTrace:on|off turn line tracing on|off diff --git a/doc/manual/syntax.txt b/doc/manual/syntax.txt index c975e7f48..b40a8ce91 100644 --- a/doc/manual/syntax.txt +++ b/doc/manual/syntax.txt @@ -12,10 +12,8 @@ Binary operators have 11 different levels of precedence. Associativity ------------- -Binary operators whose first character is ``^`` or its last character -is ``>`` are right-associative, all other binary operators are left-associative. - -Exception: The single "greater than" ``>`` operator is left-associative too. +Binary operators whose first character is ``^`` are right-associative, all +other binary operators are left-associative. Operators ending in ``>`` but longer than a single character are called `arrow like`:idx:. diff --git a/koch.nim b/koch.nim index bc7631bcc..782a55e01 100644 --- a/koch.nim +++ b/koch.nim @@ -40,7 +40,7 @@ Options: --help, -h shows this help and quits Possible Commands: boot [options] bootstraps with given command line options - install [bindir] installs to given directory + install [bindir] installs to given directory; Unix only! clean cleans Nimrod project; removes generated files web [options] generates the website and the full documentation website [options] generates only the website diff --git a/koch.nimrod.cfg b/koch.nim.cfg index 1d7acf579..1d7acf579 100644 --- a/koch.nimrod.cfg +++ b/koch.nim.cfg diff --git a/lib/impure/rdstdin.nim b/lib/impure/rdstdin.nim index 07ef13fd9..b188ead1f 100644 --- a/lib/impure/rdstdin.nim +++ b/lib/impure/rdstdin.nim @@ -1,7 +1,7 @@ # # # Nim's Runtime Library -# (c) Copyright 2012 Andreas Rumpf +# (c) Copyright 2015 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -13,6 +13,8 @@ ## is used. This suffices because Windows' console already provides the ## wanted functionality. +{.deadCodeElim: on.} + when defined(Windows): proc readLineFromStdin*(prompt: string): TaintedString {. tags: [ReadIOEffect, WriteIOEffect].} = @@ -31,9 +33,27 @@ when defined(Windows): stdout.write(prompt) result = readLine(stdin, line) + proc readPasswordFromStdin*(prompt: string, password: var TaintedString) = + ## Reads a `password` from stdin without printing it. `password` must not + ## be ``nil``! + proc getch(): cint {.header: "<conio.h>", importc: "_getch".} + + password.setLen(0) + var c: char + echo prompt + while true: + c = getch().char + case c + of '\r', chr(0xA): + break + of '\b': + password.setLen(password.len - 1) + else: + password.add(c) + else: - import readline, history - + import readline, history, termios, unsigned + proc readLineFromStdin*(prompt: string): TaintedString {. tags: [ReadIOEffect, WriteIOEffect].} = var buffer = readline.readLine(prompt) @@ -55,8 +75,24 @@ else: result = true # initialization: - # disable auto-complete: + # disable auto-complete: proc doNothing(a, b: cint): cint {.cdecl, procvar.} = discard - + discard readline.bind_key('\t'.ord, doNothing) + proc readPasswordFromStdin*(prompt: string, password: var TaintedString) = + password.setLen(0) + let fd = stdin.getFileHandle() + var cur, old: Termios + discard fd.tcgetattr(cur.addr) + old = cur + cur.lflag = cur.lflag and not Tcflag(ECHO) + discard fd.tcsetattr(TCSADRAIN, cur.addr) + stdout.write prompt + discard stdin.readLine(password) + discard fd.tcsetattr(TCSADRAIN, old.addr) + +proc readPasswordFromStdin*(prompt: string): TaintedString = + ## Reads a password from stdin without printing it. + result = TaintedString("") + readPasswordFromStdin(prompt, result) diff --git a/lib/nimbase.h b/lib/nimbase.h index b72e60ac2..50c7968ac 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -379,7 +379,7 @@ static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); } # define GC_GUARD #endif -/* Test to see if nimrod and the C compiler agree on the size of a pointer. +/* Test to see if Nim and the C compiler agree on the size of a pointer. On disagreement, your C compiler will say something like: "error: 'assert_numbits' declared as an array with a negative size" */ typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1]; @@ -390,3 +390,12 @@ typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof( #else # define NIM_EXTERNC #endif + +/* ---------------- platform specific includes ----------------------- */ + +/* VxWorks related includes */ +#if defined(__VXWORKS__) +# include <sys/types.h> +# include <types/vxWind.h> +# include <tool/gnu/toolMacros.h> +#endif diff --git a/lib/nimrtl.nimrod.cfg b/lib/nimrtl.nim.cfg index b60de183a..b60de183a 100644 --- a/lib/nimrtl.nimrod.cfg +++ b/lib/nimrtl.nim.cfg diff --git a/lib/posix/termios.nim b/lib/posix/termios.nim index 88aed73c8..830e8a207 100644 --- a/lib/posix/termios.nim +++ b/lib/posix/termios.nim @@ -18,7 +18,7 @@ const NCCS* = 32 type - Termios* = object {.importc: "struct termios", header: "termios.h>", final, pure.} + Termios* = object {.importc: "struct termios", header: "<termios.h>", final, pure.} iflag*: Tcflag # input mode flags oflag*: Tcflag # output mode flags cflag*: Tcflag # control mode flags @@ -203,62 +203,62 @@ const # Compare a character C to a value VAL from the `cc' array in a # `struct termios'. If VAL is _POSIX_VDISABLE, no character can match it. -template CCEQ*(val, c: expr): expr = - ((c) == (val) and (val) != POSIX_VDISABLE) +template cceq*(val, c: expr): expr = + c == val and val != POSIX_VDISABLE # Return the output baud rate stored in *TERMIOS_P. -proc cfgetospeed*(termios: ptr Termios): Speed {.importc: "cfgetospeed", +proc cfGetOspeed*(termios: ptr Termios): Speed {.importc: "cfgetospeed", header: "<termios.h>".} # Return the input baud rate stored in *TERMIOS_P. -proc cfgetispeed*(termios: ptr Termios): Speed {.importc: "cfgetispeed", +proc cfGetIspeed*(termios: ptr Termios): Speed {.importc: "cfgetispeed", header: "<termios.h>".} # Set the output baud rate stored in *TERMIOS_P to SPEED. -proc cfsetospeed*(termios: ptr Termios; speed: Speed): cint {. +proc cfSetOspeed*(termios: ptr Termios; speed: Speed): cint {. importc: "cfsetospeed", header: "<termios.h>".} # Set the input baud rate stored in *TERMIOS_P to SPEED. -proc cfsetispeed*(termios: ptr Termios; speed: Speed): cint {. +proc cfSetIspeed*(termios: ptr Termios; speed: Speed): cint {. importc: "cfsetispeed", header: "<termios.h>".} # Set both the input and output baud rates in *TERMIOS_OP to SPEED. -proc cfsetspeed*(termios: ptr Termios; speed: Speed): cint {. +proc cfSetSpeed*(termios: ptr Termios; speed: Speed): cint {. importc: "cfsetspeed", header: "<termios.h>".} # Put the state of FD into *TERMIOS_P. -proc tcgetattr*(fd: cint; termios: ptr Termios): cint {. +proc tcGetAttr*(fd: cint; termios: ptr Termios): cint {. importc: "tcgetattr", header: "<termios.h>".} # Set the state of FD to *TERMIOS_P. # Values for OPTIONAL_ACTIONS (TCSA*) are in <bits/termios.h>. -proc tcsetattr*(fd: cint; optional_actions: cint; termios: ptr Termios): cint {. +proc tcSetAttr*(fd: cint; optional_actions: cint; termios: ptr Termios): cint {. importc: "tcsetattr", header: "<termios.h>".} # Set *TERMIOS_P to indicate raw mode. -proc cfmakeraw*(termios: ptr Termios) {.importc: "cfmakeraw", +proc cfMakeRaw*(termios: ptr Termios) {.importc: "cfmakeraw", header: "<termios.h>".} # Send zero bits on FD. -proc tcsendbreak*(fd: cint; duration: cint): cint {.importc: "tcsendbreak", +proc tcSendBreak*(fd: cint; duration: cint): cint {.importc: "tcsendbreak", header: "<termios.h>".} # Wait for pending output to be written on FD. # # This function is a cancellation point and therefore not marked with # . -proc tcdrain*(fd: cint): cint {.importc: "tcdrain", header: "<termios.h>".} +proc tcDrain*(fd: cint): cint {.importc: "tcdrain", header: "<termios.h>".} # Flush pending data on FD. # Values for QUEUE_SELECTOR (TC{I,O,IO}FLUSH) are in <bits/termios.h>. -proc tcflush*(fd: cint; queue_selector: cint): cint {.importc: "tcflush", +proc tcFlush*(fd: cint; queue_selector: cint): cint {.importc: "tcflush", header: "<termios.h>".} # Suspend or restart transmission on FD. # Values for ACTION (TC[IO]{OFF,ON}) are in <bits/termios.h>. -proc tcflow*(fd: cint; action: cint): cint {.importc: "tcflow", +proc tcFlow*(fd: cint; action: cint): cint {.importc: "tcflow", header: "<termios.h>".} # Get process group ID for session leader for controlling terminal FD. -proc tcgetsid*(fd: cint): TPid {.importc: "tcgetsid", header: "<termios.h>".} +proc tcGetSid*(fd: cint): TPid {.importc: "tcgetsid", header: "<termios.h>".} diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index 0358a9a81..20bfc5c7c 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -220,3 +220,62 @@ proc product*[T](x: openArray[seq[T]]): seq[seq[T]] = result.add(res) index = 0 indexes[index] -=1 + +proc nextPermutation*[T](x: var openarray[T]): bool {.discardable.} = + ## Calculates the next lexicographic permutation, directly modifying ``x``. + ## The result is whether a permutation happened, otherwise we have reached + ## the last-ordered permutation. + ## + ## .. code-block:: nim + ## + ## var v = @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + ## v.nextPermutation() + ## echo v + if x.len < 2: + return false + + var i = x.high + while i > 0 and x[i-1] >= x[i]: + dec i + + if i == 0: + return false + + var j = x.high + while j >= i and x[j] <= x[i-1]: + dec j + + swap x[j], x[i-1] + x.reverse(i, x.high) + + result = true + +proc prevPermutation*[T](x: var openarray[T]): bool {.discardable.} = + ## Calculates the previous lexicographic permutation, directly modifying + ## ``x``. The result is whether a permutation happened, otherwise we have + ## reached the first-ordered permutation. + ## + ## .. code-block:: nim + ## + ## var v = @[0, 1, 2, 3, 4, 5, 6, 7, 9, 8] + ## v.prevPermutation() + ## echo v + if x.len < 2: + return false + + var i = x.high + while i > 0 and x[i-1] <= x[i]: + dec i + + if i == 0: + return false + + x.reverse(i, x.high) + + var j = x.high + while j >= i and x[j-1] < x[i-1]: + dec j + + swap x[i-1], x[j] + + result = true diff --git a/lib/pure/asyncdispatch.nimrod.cfg b/lib/pure/asyncdispatch.nim.cfg index e88f8eec3..e88f8eec3 100644 --- a/lib/pure/asyncdispatch.nimrod.cfg +++ b/lib/pure/asyncdispatch.nim.cfg diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index befc9bacb..b527b9368 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -382,7 +382,7 @@ template foldr*(sequence, operation: expr): expr = result = operation result -template mapIt*(seq1, typ, pred: expr): expr = +template mapIt*(seq1, typ, op: expr): expr = ## Convenience template around the ``map`` proc to reduce typing. ## ## The template injects the ``it`` variable which you can use directly in an @@ -397,10 +397,10 @@ template mapIt*(seq1, typ, pred: expr): expr = ## assert strings == @["4", "8", "12", "16"] var result {.gensym.}: seq[typ] = @[] for it {.inject.} in items(seq1): - result.add(pred) + result.add(op) result -template mapIt*(varSeq, pred: expr) = +template mapIt*(varSeq, op: expr) = ## Convenience template around the mutable ``map`` proc to reduce typing. ## ## The template injects the ``it`` variable which you can use directly in an @@ -413,7 +413,7 @@ template mapIt*(varSeq, pred: expr) = ## assert nums[0] + nums[3] == 15 for i in 0 .. <len(varSeq): let it {.inject.} = varSeq[i] - varSeq[i] = pred + varSeq[i] = op template newSeqWith*(len: int, init: expr): expr = ## creates a new sequence, calling `init` to initialize each value. Example: diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 873e4b78e..2a40b4f1f 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -30,9 +30,28 @@ ## ## 1.3000000000000000e+00 ## true +## +## This module can also be used to comfortably create JSON using the `%*` +## operator: +## +## .. code-block:: nim +## +## var hisName = "John" +## let herAge = 31 +## var j = %* +## [ +## { +## "name": hisName, +## "age": 30 +## }, +## { +## "name": "Susan", +## "age": herAge +## } +## ] import - hashes, strutils, lexbase, streams, unicode + hashes, strutils, lexbase, streams, unicode, macros type JsonEventKind* = enum ## enumeration of all events that may occur when parsing @@ -625,6 +644,29 @@ proc `%`*(elements: openArray[JsonNode]): JsonNode = newSeq(result.elems, elements.len) for i, p in pairs(elements): result.elems[i] = p +proc toJson(x: PNimrodNode): PNimrodNode {.compiletime.} = + case x.kind + of nnkBracket: + result = newNimNode(nnkBracket) + for i in 0 .. <x.len: + result.add(toJson(x[i])) + + of nnkTableConstr: + result = newNimNode(nnkTableConstr) + for i in 0 .. <x.len: + assert x[i].kind == nnkExprColonExpr + result.add(newNimNode(nnkExprColonExpr).add(x[i][0]).add(toJson(x[i][1]))) + + else: + result = x + + result = prefix(result, "%") + +macro `%*`*(x: expr): expr = + ## Convert an expression to a JsonNode directly, without having to specify + ## `%` for every element. + result = toJson(x) + proc `==`* (a,b: JsonNode): bool = ## Check two nodes for equality if a.isNil: @@ -864,7 +906,7 @@ proc pretty*(node: JsonNode, indent = 2): string = proc `$`*(node: JsonNode): string = ## Converts `node` to its JSON Representation on one line. result = "" - toPretty(result, node, 1, false) + toPretty(result, node, 0, false) iterator items*(node: JsonNode): JsonNode = ## Iterator for the items of `node`. `node` has to be a JArray. @@ -1101,6 +1143,37 @@ when isMainModule: except: assert(false, "EInvalidIndex thrown for valid index") + # Generator: + var j = %* [{"name": "John", "age": 30}, {"name": "Susan", "age": 31}] + assert j == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}] + + var j2 = %* + [ + { + "name": "John", + "age": 30 + }, + { + "name": "Susan", + "age": 31 + } + ] + assert j2 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}] + + var name = "John" + let herAge = 30 + const hisAge = 31 + + var j3 = %* + [ { "name": "John" + , "age": herAge + } + , { "name": "Susan" + , "age": hisAge + } + ] + assert j3 == %[%{"name": %"John", "age": %30}, %{"name": %"Susan", "age": %31}] + discard """ while true: var json = stdin.readLine() diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim index bb1835ed7..de733b75c 100644 --- a/lib/pure/logging.nim +++ b/lib/pure/logging.nim @@ -186,7 +186,7 @@ proc newRollingFileLogger*(filename = defaultFilename(), ## a new log file will be started and the old will be renamed. new(result) result.levelThreshold = levelThreshold - result.fmtStr = defaultFmtStr + result.fmtStr = fmtStr result.maxLines = maxLines result.f = open(filename, mode) result.curLine = 0 diff --git a/lib/pure/nimprof.nimrod.cfg b/lib/pure/nimprof.nim.cfg index 1589e7394..1589e7394 100644 --- a/lib/pure/nimprof.nimrod.cfg +++ b/lib/pure/nimprof.nim.cfg diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 147614d3d..f01343673 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1074,8 +1074,12 @@ when defined(windows): # because we support Windows GUI applications, things get really # messy here... when useWinUnicode: - proc strEnd(cstr: WideCString, c = 0'i32): WideCString {. - importc: "wcschr", header: "<string.h>".} + when defined(cpp): + proc strEnd(cstr: WideCString, c = 0'i32): WideCString {. + importcpp: "(NI16*)wcschr((const wchar_t *)#, #)", header: "<string.h>".} + else: + proc strEnd(cstr: WideCString, c = 0'i32): WideCString {. + importc: "wcschr", header: "<string.h>".} else: proc strEnd(cstr: cstring, c = 0'i32): cstring {. importc: "strchr", header: "<string.h>".} diff --git a/lib/pure/smtp.nimrod.cfg b/lib/pure/smtp.nim.cfg index 521e21de4..521e21de4 100644 --- a/lib/pure/smtp.nimrod.cfg +++ b/lib/pure/smtp.nim.cfg diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim index 5b7149d8e..727d5a386 100644 --- a/lib/pure/strtabs.nim +++ b/lib/pure/strtabs.nim @@ -112,7 +112,7 @@ proc `[]`*(t: StringTableRef, key: string): string {.rtl, extern: "nstGet".} = proc mget*(t: StringTableRef, key: string): var string {. rtl, extern: "nstTake".} = ## retrieves the location at ``t[key]``. If `key` is not in `t`, the - ## ``EInvalidKey`` exception is raised. + ## ``KeyError`` exception is raised. var index = rawGet(t, key) if index >= 0: result = t.data[index].val else: raise newException(KeyError, "key does not exist: " & key) @@ -158,7 +158,7 @@ proc getValue(t: StringTableRef, flags: set[FormatFlag], key: string): string = else: result = "" if result.len == 0: if useKey in flags: result = '$' & key - elif not (useEmpty in flags): raiseFormatException(key) + elif useEmpty notin flags: raiseFormatException(key) proc newStringTable*(mode: StringTableMode): StringTableRef {. rtl, extern: "nst$1".} = diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim index 8dc9fe0d4..f4e42ee63 100644 --- a/lib/pure/unittest.nim +++ b/lib/pure/unittest.nim @@ -39,6 +39,7 @@ when declared(stdout): when not defined(ECMAScript): import terminal + system.addQuitProc(resetAttributes) type TestStatus* = enum OK, FAILED @@ -234,5 +235,3 @@ if envOutLvl.len > 0: if $opt == envOutLvl: outputLevel = opt break - -system.addQuitProc(resetAttributes) diff --git a/lib/system.nim b/lib/system.nim index 12c5c6303..ef70a2672 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -343,10 +343,10 @@ type ## ## Each exception has to inherit from `Exception`. See the full `exception ## hierarchy`_. - parent: ref Exception ## parent exception (can be used as a stack) - name: cstring ## The exception's name is its Nim identifier. - ## This field is filled automatically in the - ## ``raise`` statement. + parent*: ref Exception ## parent exception (can be used as a stack) + name: cstring ## The exception's name is its Nim identifier. + ## This field is filled automatically in the + ## ``raise`` statement. msg* {.exportc: "message".}: string ## the exception's message. Not ## providing an exception message ## is bad style. @@ -2194,7 +2194,8 @@ elif hostOS != "standalone": inc(i) {.pop.} -proc echo*(x: varargs[expr, `$`]) {.magic: "Echo", tags: [WriteIOEffect], benign.} +proc echo*(x: varargs[expr, `$`]) {.magic: "Echo", tags: [WriteIOEffect], + benign, sideEffect.} ## Writes and flushes the parameters to the standard output. ## ## Special built-in that takes a variable number of arguments. Each argument @@ -3160,7 +3161,7 @@ when hostOS != "standalone": x[j+i] = item[j] inc(j) -proc compiles*(x): bool {.magic: "Compiles", noSideEffect.} = +proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect.} = ## Special compile-time procedure that checks whether `x` can be compiled ## without any semantic error. ## This can be used to check whether a type supports some operation: diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim index e0d99cf88..539e37aaf 100644 --- a/lib/system/dyncalls.nim +++ b/lib/system/dyncalls.nim @@ -80,15 +80,22 @@ elif defined(windows) or defined(dos): # Native Windows Implementation # ======================================================================= # - type - THINSTANCE {.importc: "HINSTANCE".} = pointer + when defined(cpp): + type + THINSTANCE {.importc: "HINSTANCE".} = object + x: pointer + proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {. + importcpp: "(void*)GetProcAddress(@)", header: "<windows.h>", stdcall.} + else: + type + THINSTANCE {.importc: "HINSTANCE".} = pointer + proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {. + importc: "GetProcAddress", header: "<windows.h>", stdcall.} proc freeLibrary(lib: THINSTANCE) {. importc: "FreeLibrary", header: "<windows.h>", stdcall.} proc winLoadLibrary(path: cstring): THINSTANCE {. importc: "LoadLibraryA", header: "<windows.h>", stdcall.} - proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {. - importc: "GetProcAddress", header: "<windows.h>", stdcall.} proc nimUnloadLibrary(lib: TLibHandle) = freeLibrary(cast[THINSTANCE](lib)) diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index 7908fbe4d..2e254c87b 100644 --- a/lib/system/sysio.nim +++ b/lib/system/sysio.nim @@ -183,11 +183,17 @@ proc rawEchoNL() {.inline, compilerproc.} = write(stdout, "\n") when (defined(windows) and not defined(useWinAnsi)) or defined(nimdoc): include "system/widestrs" -when defined(windows) and not defined(useWinAnsi): - proc wfopen(filename, mode: WideCString): pointer {. - importc: "_wfopen", nodecl.} - proc wfreopen(filename, mode: WideCString, stream: File): File {. - importc: "_wfreopen", nodecl.} +when defined(windows) and not defined(useWinAnsi): + when defined(cpp): + proc wfopen(filename, mode: WideCString): pointer {. + importcpp: "_wfopen((const wchar_t*)#, (const wchar_t*)#)", nodecl.} + proc wfreopen(filename, mode: WideCString, stream: File): File {. + importc: "_wfreopen((const wchar_t*)#, (const wchar_t*)#)", nodecl.} + else: + proc wfopen(filename, mode: WideCString): pointer {. + importc: "_wfopen", nodecl.} + proc wfreopen(filename, mode: WideCString, stream: File): File {. + importc: "_wfreopen", nodecl.} proc fopen(filename, mode: cstring): pointer = var f = newWideCString(filename) diff --git a/tests/assert/tfailedassert.nim b/tests/assert/tfailedassert.nim index d03d3136b..8766321bf 100644 --- a/tests/assert/tfailedassert.nim +++ b/tests/assert/tfailedassert.nim @@ -3,7 +3,7 @@ discard """ WARNING: false first assertion from bar ERROR: false second assertion from bar -1 -tfailedassert.nim:27 false assertion from foo +tests/assert/tfailedassert.nim:27 false assertion from foo ''' """ diff --git a/tests/bind/tnicerrorforsymchoice.nim b/tests/bind/tnicerrorforsymchoice.nim index e1ff090dd..bf6d92927 100644 --- a/tests/bind/tnicerrorforsymchoice.nim +++ b/tests/bind/tnicerrorforsymchoice.nim @@ -1,6 +1,6 @@ discard """ line: 18 - errormsg: "type mismatch: got (proc (TScgi) | proc (AsyncSocket, StringTableRef, string){.gcsafe.})" + errormsg: "type mismatch: got (proc (TScgi) | proc (AsyncSocket, StringTableRef, string)" """ #bug #442 diff --git a/tests/clearmsg/ta.nim b/tests/clearmsg/ta.nim index b21522d12..38449c319 100644 --- a/tests/clearmsg/ta.nim +++ b/tests/clearmsg/ta.nim @@ -1,5 +1,5 @@ discard """ - errormsg: 'type mismatch: got (mc.typ)' + errormsg: "type mismatch: got (mc.typ)" line: 12 """ diff --git a/tests/closure/ttimeinfo.nim b/tests/closure/ttimeinfo.nim new file mode 100644 index 000000000..3138ae72e --- /dev/null +++ b/tests/closure/ttimeinfo.nim @@ -0,0 +1,15 @@ +# bug #2073 + +import sequtils +import times + +# 1 +proc f(n: int): TimeInfo = + TimeInfo(year: n, month: mJan, monthday: 1) + +echo toSeq(2000 || 2015).map(f) + +# 2 +echo toSeq(2000 || 2015).map(proc (n: int): TimeInfo = + TimeInfo(year: n, month: mJan, monthday: 1) +) diff --git a/tests/cpp/trawsockets.nim b/tests/cpp/trawsockets.nim new file mode 100644 index 000000000..d034245d0 --- /dev/null +++ b/tests/cpp/trawsockets.nim @@ -0,0 +1,5 @@ +discard """ + cmd: "nim cpp $target" +""" + +import rawsockets diff --git a/tests/cpp/ttypeinfo.nim b/tests/cpp/ttypeinfo.nim new file mode 100644 index 000000000..e72883dbf --- /dev/null +++ b/tests/cpp/ttypeinfo.nim @@ -0,0 +1,5 @@ +discard """ + cmd: "nim cpp $target" +""" + +import typeinfo diff --git a/tests/dll/client.nimrod.cfg b/tests/dll/client.nim.cfg index 0e044a829..0e044a829 100644 --- a/tests/dll/client.nimrod.cfg +++ b/tests/dll/client.nim.cfg diff --git a/tests/dll/server.nimrod.cfg b/tests/dll/server.nim.cfg index 02393ba8b..02393ba8b 100644 --- a/tests/dll/server.nimrod.cfg +++ b/tests/dll/server.nim.cfg diff --git a/tests/effects/teffects1.nim b/tests/effects/teffects1.nim index 27f89f5fa..ea1ea7b21 100644 --- a/tests/effects/teffects1.nim +++ b/tests/effects/teffects1.nim @@ -1,5 +1,4 @@ discard """ - line: 2166 file: "system.nim" errormsg: "can raise an unlisted exception: ref IOError" """ diff --git a/tests/exprs/thighCString.nim b/tests/exprs/thighCString.nim new file mode 100644 index 000000000..543966df4 --- /dev/null +++ b/tests/exprs/thighCString.nim @@ -0,0 +1,6 @@ +discard """ + output: "5" +""" +let test = cstring("foobar") + +echo high(test) diff --git a/tests/generics/t1056.nim b/tests/generics/t1056.nim index 73a24a76a..b1fe25894 100644 --- a/tests/generics/t1056.nim +++ b/tests/generics/t1056.nim @@ -1,6 +1,5 @@ discard """ output: '''TMatrix[3, 3, system.int] -3 3''' """ @@ -22,5 +21,5 @@ proc echoMat2(a: TMat2) = var m = TMatrix[3,3,int](data: [1,2,3,4,5,6,7,8,9]) echoMatrix m -echoMat2 m +#echoMat2 m diff --git a/tests/iter/tconcat.nim b/tests/iter/tconcat.nim new file mode 100644 index 000000000..477ac5e26 --- /dev/null +++ b/tests/iter/tconcat.nim @@ -0,0 +1,24 @@ +discard """ + output: '''1 +2 +3 +4 +20 +21 +22 +23''' +""" + +proc toIter*[T](s: Slice[T]): iterator: T = + iterator it: T {.closure.} = + for x in s.a..s.b: + yield x + return it + +iterator concat*[T](its: varargs[T, toIter]): auto = + for i in its: + for x in i(): + yield x + +for i in concat(1..4, 20..23): + echo i diff --git a/tests/macros/macro_bug.nim b/tests/macros/macro_bug.nim new file mode 100644 index 000000000..0d0fa76ac --- /dev/null +++ b/tests/macros/macro_bug.nim @@ -0,0 +1,17 @@ +import macros + +macro macro_bug*(s: stmt): stmt {.immediate.} = + s.expectKind({nnkProcDef, nnkMethodDef}) + + var params = s.params + + let genericParams = s[2] + result = newNimNode(nnkProcDef).add( + s.name, s[1], genericParams, params, pragma(s), newEmptyNode()) + + var body = body(s) + + # Fails here. + var call = newCall("macro_bug", s.params[1][0]) + body.insert(0, call) + result.add(body) diff --git a/tests/macros/tsame_name_497.nim b/tests/macros/tsame_name_497.nim new file mode 100644 index 000000000..e49f9f6d8 --- /dev/null +++ b/tests/macros/tsame_name_497.nim @@ -0,0 +1,5 @@ +import macro_bug + +type TObj = object + +proc f(o: TObj) {.macro_bug.} = discard diff --git a/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim b/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim index d079a2e72..08f1dad50 100644 --- a/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim +++ b/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim @@ -74,7 +74,7 @@ type contacts*: PContact stamp*: TTimestamp handler*: PCollisionHandler - swappedColl*: bool32 + swappedColl*: Bool32 state*: TArbiterState PCollisionHandler* = ptr TCollisionHandler TCollisionHandler*{.pf.} = object @@ -108,7 +108,7 @@ type #/ Collision begin event function callback type. #/ Returning false from a begin callback causes the collision to be ignored until #/ the the separate callback is called when the objects stop colliding. - TCollisionBeginFunc* = proc (arb: PArbiter; space: PSpace; data: pointer): Bool{. + TCollisionBeginFunc* = proc (arb: PArbiter; space: PSpace; data: pointer): bool{. cdecl.} #/ Collision pre-solve event function callback type. #/ Returning false from a pre-step callback causes the collision to be ignored until the next step. @@ -142,14 +142,14 @@ type PSpatialIndex = ptr TSpatialIndex TSpatialIndex{.pf.} = object klass: PSpatialIndexClass - bbfunc: TSpatialIndexBBFunc + bbfun: TSpatialIndexBBFunc staticIndex: PSpatialIndex dynamicIndex: PSpatialIndex TSpatialIndexDestroyImpl* = proc (index: PSpatialIndex){.cdecl.} TSpatialIndexCountImpl* = proc (index: PSpatialIndex): cint{.cdecl.} TSpatialIndexEachImpl* = proc (index: PSpatialIndex; - func: TSpatialIndexIteratorFunc; data: pointer){. + fun: TSpatialIndexIteratorFunc; data: pointer){. cdecl.} TSpatialIndexContainsImpl* = proc (index: PSpatialIndex; obj: pointer; hashid: THashValue): Bool32 {.cdecl.} @@ -161,15 +161,15 @@ type TSpatialIndexReindexObjectImpl* = proc (index: PSpatialIndex; obj: pointer; hashid: THashValue){.cdecl.} TSpatialIndexReindexQueryImpl* = proc (index: PSpatialIndex; - func: TSpatialIndexQueryFunc; data: pointer){.cdecl.} + fun: TSpatialIndexQueryFunc; data: pointer){.cdecl.} TSpatialIndexPointQueryImpl* = proc (index: PSpatialIndex; point: TVector; - func: TSpatialIndexQueryFunc; + fun: TSpatialIndexQueryFunc; data: pointer){.cdecl.} TSpatialIndexSegmentQueryImpl* = proc (index: PSpatialIndex; obj: pointer; - a: TVector; b: TVector; t_exit: CpFloat; func: TSpatialIndexSegmentQueryFunc; + a: TVector; b: TVector; t_exit: CpFloat; fun: TSpatialIndexSegmentQueryFunc; data: pointer){.cdecl.} TSpatialIndexQueryImpl* = proc (index: PSpatialIndex; obj: pointer; - bb: TBB; func: TSpatialIndexQueryFunc; + bb: TBB; fun: TSpatialIndexQueryFunc; data: pointer){.cdecl.} PSpatialIndexClass* = ptr TSpatialIndexClass TSpatialIndexClass*{.pf.} = object @@ -286,7 +286,7 @@ type CP_CIRCLE_SHAPE, CP_SEGMENT_SHAPE, CP_POLY_SHAPE, CP_NUM_SHAPES TShapeCacheDataImpl* = proc (shape: PShape; p: TVector; rot: TVector): TBB{.cdecl.} TShapeDestroyImpl* = proc (shape: PShape){.cdecl.} - TShapePointQueryImpl* = proc (shape: PShape; p: TVector): bool32 {.cdecl.} + TShapePointQueryImpl* = proc (shape: PShape; p: TVector): Bool32 {.cdecl.} TShapeSegmentQueryImpl* = proc (shape: PShape; a: TVector; b: TVector; info: PSegmentQueryInfo){.cdecl.} PShapeClass* = ptr TShapeClass @@ -427,7 +427,7 @@ defGetter(PSpace, CpFloat, currDt, CurrentTimeStep) #/ returns true from inside a callback and objects cannot be added/removed. -proc isLocked*(space: PSpace): Bool{.inline.} = +proc isLocked*(space: PSpace): bool{.inline.} = result = space.locked.bool #/ Set a default collision handler for this space. @@ -478,24 +478,24 @@ proc removeBody*(space: PSpace; body: PBody){. proc RemoveConstraint*(space: PSpace; constraint: PConstraint){. cdecl, importc: "cpSpaceRemoveConstraint", dynlib: Lib.} #/ Test if a collision shape has been added to the space. -proc containsShape*(space: PSpace; shape: PShape): Bool{. +proc containsShape*(space: PSpace; shape: PShape): bool{. cdecl, importc: "cpSpaceContainsShape", dynlib: Lib.} #/ Test if a rigid body has been added to the space. -proc containsBody*(space: PSpace; body: PBody): Bool{. +proc containsBody*(space: PSpace; body: PBody): bool{. cdecl, importc: "cpSpaceContainsBody", dynlib: Lib.} #/ Test if a constraint has been added to the space. -proc containsConstraint*(space: PSpace; constraint: PConstraint): Bool{. +proc containsConstraint*(space: PSpace; constraint: PConstraint): bool{. cdecl, importc: "cpSpaceContainsConstraint", dynlib: Lib.} #/ Schedule a post-step callback to be called when cpSpaceStep() finishes. #/ @c obj is used a key, you can only register one callback per unique value for @c obj -proc addPostStepCallback*(space: PSpace; func: TPostStepFunc; +proc addPostStepCallback*(space: PSpace; fun: TPostStepFunc; obj: pointer; data: pointer){. cdecl, importc: "cpSpaceAddPostStepCallback", dynlib: Lib.} #/ Query the space at a point and call @c func for each shape found. proc pointQuery*(space: PSpace; point: TVector; layers: TLayers; - group: TGroup; func: TSpacePointQueryFunc; data: pointer){. + group: TGroup; fun: TSpacePointQueryFunc; data: pointer){. cdecl, importc: "cpSpacePointQuery", dynlib: Lib.} #/ Query the space at a point and return the first shape found. Returns NULL if no shapes were found. @@ -506,7 +506,7 @@ proc pointQueryFirst*(space: PSpace; point: TVector; layers: TLayers; #/ Perform a directed line segment query (like a raycast) against the space calling @c func for each shape intersected. proc segmentQuery*(space: PSpace; start: TVector; to: TVector; layers: TLayers; group: TGroup; - func: TSpaceSegmentQueryFunc; data: pointer){. + fun: TSpaceSegmentQueryFunc; data: pointer){. cdecl, importc: "cpSpaceSegmentQuery", dynlib: Lib.} #/ Perform a directed line segment query (like a raycast) against the space and return the first shape hit. Returns NULL if no shapes were hit. proc segmentQueryFirst*(space: PSpace; start: TVector; to: TVector; @@ -517,26 +517,26 @@ proc segmentQueryFirst*(space: PSpace; start: TVector; to: TVector; #/ Perform a fast rectangle query on the space calling @c func for each shape found. #/ Only the shape's bounding boxes are checked for overlap, not their full shape. proc BBQuery*(space: PSpace; bb: TBB; layers: TLayers; group: TGroup; - func: TSpaceBBQueryFunc; data: pointer){. + fun: TSpaceBBQueryFunc; data: pointer){. cdecl, importc: "cpSpaceBBQuery", dynlib: Lib.} #/ Query a space for any shapes overlapping the given shape and call @c func for each shape found. -proc shapeQuery*(space: PSpace; shape: PShape; func: TSpaceShapeQueryFunc; data: pointer): Bool {. +proc shapeQuery*(space: PSpace; shape: PShape; fun: TSpaceShapeQueryFunc; data: pointer): bool {. cdecl, importc: "cpSpaceShapeQuery", dynlib: Lib.} #/ Call cpBodyActivate() for any shape that is overlaps the given shape. proc activateShapesTouchingShape*(space: PSpace; shape: PShape){. cdecl, importc: "cpSpaceActivateShapesTouchingShape", dynlib: Lib.} #/ Call @c func for each body in the space. -proc eachBody*(space: PSpace; func: TSpaceBodyIteratorFunc; data: pointer){. +proc eachBody*(space: PSpace; fun: TSpaceBodyIteratorFunc; data: pointer){. cdecl, importc: "cpSpaceEachBody", dynlib: Lib.} #/ Call @c func for each shape in the space. -proc eachShape*(space: PSpace; func: TSpaceShapeIteratorFunc; +proc eachShape*(space: PSpace; fun: TSpaceShapeIteratorFunc; data: pointer){. cdecl, importc: "cpSpaceEachShape", dynlib: Lib.} #/ Call @c func for each shape in the space. -proc eachConstraint*(space: PSpace; func: TSpaceConstraintIteratorFunc; +proc eachConstraint*(space: PSpace; fun: TSpaceConstraintIteratorFunc; data: pointer){. cdecl, importc: "cpSpaceEachConstraint", dynlib: Lib.} #/ Update the collision detection info for the static shapes in the space. @@ -674,7 +674,7 @@ proc dist*(v1, v2: TVector): CpFloat {.inline.} = proc distsq*(v1, v2: TVector): CpFloat {.inline.} = result = (v1 - v2).lenSq #vlengthsq(vsub(v1, v2)) #/ Returns true if the distance between v1 and v2 is less than dist. -proc near*(v1, v2: TVector; dist: CpFloat): Bool{.inline.} = +proc near*(v1, v2: TVector; dist: CpFloat): bool{.inline.} = result = v1.distSq(v2) < dist * dist @@ -706,13 +706,13 @@ proc Sleep*(body: PBody){.importc: "cpBodySleep", dynlib: Lib.} proc SleepWithGroup*(body: PBody; group: PBody){. importc: "cpBodySleepWithGroup", dynlib: Lib.} #/ Returns true if the body is sleeping. -proc isSleeping*(body: PBody): Bool {.inline.} = +proc isSleeping*(body: PBody): bool {.inline.} = return body.node.root != nil #/ Returns true if the body is static. proc isStatic*(body: PBody): bool {.inline.} = return body.node.idleTime == CpInfinity #/ Returns true if the body has not been added to a space. -proc isRogue*(body: PBody): Bool {.inline.} = +proc isRogue*(body: PBody): bool {.inline.} = return body.space == nil # #define CP_DefineBodyStructGetter(type, member, name) \ @@ -808,15 +808,15 @@ proc kineticEnergy*(body: PBOdy): CpFloat = result = (body.v.dot(body.v) * body.m) + (body.w * body.w * body.i) #/ Call @c func once for each shape attached to @c body and added to the space. -proc eachShape*(body: PBody; func: TBodyShapeIteratorFunc; +proc eachShape*(body: PBody; fun: TBodyShapeIteratorFunc; data: pointer){. cdecl, importc: "cpBodyEachShape", dynlib: Lib.} #/ Call @c func once for each constraint attached to @c body and added to the space. -proc eachConstraint*(body: PBody; func: TBodyConstraintIteratorFunc; +proc eachConstraint*(body: PBody; fun: TBodyConstraintIteratorFunc; data: pointer) {. cdecl, importc: "cpBodyEachConstraint", dynlib: Lib.} #/ Call @c func once for each arbiter that is currently active on the body. -proc eachArbiter*(body: PBody; func: TBodyArbiterIteratorFunc; +proc eachArbiter*(body: PBody; fun: TBodyArbiterIteratorFunc; data: pointer){. cdecl, importc: "cpBodyEachArbiter", dynlib: Lib.} #/ Allocate a spatial hash. @@ -824,10 +824,10 @@ proc SpaceHashAlloc*(): PSpaceHash{. cdecl, importc: "cpSpaceHashAlloc", dynlib: Lib.} #/ Initialize a spatial hash. proc SpaceHashInit*(hash: PSpaceHash; celldim: CpFloat; numcells: cint; - bbfunc: TSpatialIndexBBFunc; staticIndex: PSpatialIndex): PSpatialIndex{. + bbfun: TSpatialIndexBBFunc; staticIndex: PSpatialIndex): PSpatialIndex{. cdecl, importc: "cpSpaceHashInit", dynlib: Lib.} #/ Allocate and initialize a spatial hash. -proc SpaceHashNew*(celldim: CpFloat; cells: cint; bbfunc: TSpatialIndexBBFunc; +proc SpaceHashNew*(celldim: CpFloat; cells: cint; bbfun: TSpatialIndexBBFunc; staticIndex: PSpatialIndex): PSpatialIndex{. cdecl, importc: "cpSpaceHashNew", dynlib: Lib.} #/ Change the cell dimensions and table size of the spatial hash to tune it. @@ -842,18 +842,18 @@ proc SpaceHashResize*(hash: PSpaceHash; celldim: CpFloat; numcells: cint){. #/ Allocate a bounding box tree. proc BBTreeAlloc*(): PBBTree{.cdecl, importc: "cpBBTreeAlloc", dynlib: Lib.} #/ Initialize a bounding box tree. -proc BBTreeInit*(tree: PBBTree; bbfunc: TSpatialIndexBBFunc; +proc BBTreeInit*(tree: PBBTree; bbfun: TSpatialIndexBBFunc; staticIndex: ptr TSpatialIndex): ptr TSpatialIndex{.cdecl, importc: "cpBBTreeInit", dynlib: Lib.} #/ Allocate and initialize a bounding box tree. -proc BBTreeNew*(bbfunc: TSpatialIndexBBFunc; staticIndex: PSpatialIndex): PSpatialIndex{. +proc BBTreeNew*(bbfun: TSpatialIndexBBFunc; staticIndex: PSpatialIndex): PSpatialIndex{. cdecl, importc: "cpBBTreeNew", dynlib: Lib.} #/ Perform a static top down optimization of the tree. proc BBTreeOptimize*(index: PSpatialIndex){. cdecl, importc: "cpBBTreeOptimize", dynlib: Lib.} #/ Set the velocity function for the bounding box tree to enable temporal coherence. -proc BBTreeSetVelocityFunc*(index: PSpatialIndex; func: TBBTreeVelocityFunc){. +proc BBTreeSetVelocityFunc*(index: PSpatialIndex; fun: TBBTreeVelocityFunc){. cdecl, importc: "cpBBTreeSetVelocityFunc", dynlib: Lib.} #MARK: Single Axis Sweep @@ -864,12 +864,12 @@ proc Sweep1DAlloc*(): ptr TSweep1D{.cdecl, importc: "cpSweep1DAlloc", dynlib: Lib.} #/ Initialize a 1D sort and sweep broadphase. -proc Sweep1DInit*(sweep: ptr TSweep1D; bbfunc: TSpatialIndexBBFunc; +proc Sweep1DInit*(sweep: ptr TSweep1D; bbfun: TSpatialIndexBBFunc; staticIndex: ptr TSpatialIndex): ptr TSpatialIndex{.cdecl, importc: "cpSweep1DInit", dynlib: Lib.} #/ Allocate and initialize a 1D sort and sweep broadphase. -proc Sweep1DNew*(bbfunc: TSpatialIndexBBFunc; staticIndex: ptr TSpatialIndex): ptr TSpatialIndex{. +proc Sweep1DNew*(bbfun: TSpatialIndexBBFunc; staticIndex: ptr TSpatialIndex): ptr TSpatialIndex{. cdecl, importc: "cpSweep1DNew", dynlib: Lib.} @@ -1359,7 +1359,7 @@ defCProp(SlideJoint, TVector, anchr2, Anchr2) defCProp(SlideJoint, CpFloat, min, Min) defCProp(SlideJoint, CpFloat, max, Max) -proc pivotJointGetClass*(): PConstraintClass {. +proc PivotJointGetClass*(): PConstraintClass {. cdecl, importc: "cpPivotJointGetClass", dynlib: Lib.} #/ Allocate a pivot joint diff --git a/tests/manyloc/keineschweine/dependencies/enet/enet.nim b/tests/manyloc/keineschweine/dependencies/enet/enet.nim index df1b743ee..93857207a 100644 --- a/tests/manyloc/keineschweine/dependencies/enet/enet.nim +++ b/tests/manyloc/keineschweine/dependencies/enet/enet.nim @@ -20,7 +20,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. const Lib = "libenet.so.1(|.0.3)" -{.deadCodeElim: ON.} +{.deadCodeElim: on.} const ENET_VERSION_MAJOR* = 1 ENET_VERSION_MINOR* = 3 diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim index 44d00db53..4f2fb1ea3 100644 --- a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim +++ b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim @@ -9,15 +9,6 @@ template defPacketImports*(): stmt {.immediate, dirty.} = import macros, macro_dsl, estreams from strutils import format -proc `$`*[T](x: seq[T]): string = - result = "[seq len=" - result.add($x.len) - result.add ':' - for i in 0.. <len(x): - result.add " " - result.add($x[i]) - result.add ']' - macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} = result = newNimNode(nnkStmtList) let @@ -293,4 +284,4 @@ when isMainModule: for itm in test.x: echo(itm) test.pack(s) - echo(repr(s.data)) \ No newline at end of file + echo(repr(s.data)) diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim index 0d09d40e3..1071ec767 100644 --- a/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim +++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim @@ -221,10 +221,10 @@ type TTransform* {.pf.} = object matrix*: array[0..8, cfloat] TColor* {.pf.} = object - r*: Uint8 - g*: Uint8 - b*: Uint8 - a*: Uint8 + r*: uint8 + g*: uint8 + b*: uint8 + a*: uint8 PFloatRect* = ptr TFloatRect TFloatRect*{.pf.} = object left*: cfloat @@ -306,7 +306,7 @@ proc close*(window: PRenderWindow) {. proc isOpen*(window: PRenderWindow): bool {. cdecl, importc: "sfRenderWindow_isOpen", dynlib: LibG.} -#void sfRenderWindow_setIcon(sfRenderWindow* renderWindow, unsigned int width, unsigned int height, const sfUint8* pixels); +#void sfRenderWindow_setIcon(sfRenderWindow* renderWindow, unsigned int width, unsigned int height, const sfuint8* pixels); #proc setIcon*(window: PRenderWindow, width, height: cint, pixels: seq[uint8]) {. # cdecl, importc: "sfRenderWindow_setIcon", dynlib: LibG.} @@ -395,7 +395,7 @@ proc capture*(window: PRenderWindow): PImage {. cdecl, importc: "sfRenderWindow_capture", dynlib: LibG.} #Construct a new render texture -proc newRenderTexture*(width, height: cint; depthBuffer: Bool): PRenderTexture {. +proc newRenderTexture*(width, height: cint; depthBuffer: bool): PRenderTexture {. cdecl, importc: "sfRenderTexture_create", dynlib: LibG.} #Destroy an existing render texture proc destroy*(renderTexture: PRenderTexture){. @@ -522,9 +522,9 @@ proc copy*(font: PFont): PFont {. cdecl, importc: "sfFont_copy", dynlib: LibG.} proc destroy*(font: PFont) {. cdecl, importc: "sfFont_destroy", dynlib: LibG.} -proc getGlyph*(font: PFont, codePoint: Uint32, characterSize: cint, bold: bool): TGlyph{. +proc getGlyph*(font: PFont, codePoint: uint32, characterSize: cint, bold: bool): TGlyph{. cdecl, importc: "sfFont_getGlyph", dynlib: LibG.} -proc getKerning*(font: PFont, first: Uint32, second: Uint32, characterSize: cint): cint {. +proc getKerning*(font: PFont, first: uint32, second: uint32, characterSize: cint): cint {. cdecl, importc: "sfFont_getKerning", dynlib: LibG.} proc getLineSpacing*(font: PFont, characterSize: cint): cint {. cdecl, importc: "sfFont_getLineSpacing", dynlib: LibG.} @@ -882,7 +882,7 @@ proc getInverseTransform*(text: PText): TTransform {. cdecl, importc: "sfText_getInverseTransform", dynlib: LibG.} proc setString*(text: PText, string: cstring) {. cdecl, importc: "sfText_setString", dynlib: LibG.} -proc setUnicodeString*(text: PText, string: ptr Uint32) {. +proc setUnicodeString*(text: PText, string: ptr uint32) {. cdecl, importc: "sfText_setUnicodeString", dynlib: LibG.} proc setFont*(text: PText, font: PFont) {. cdecl, importc: "sfText_setFont", dynlib: LibG.} @@ -894,13 +894,13 @@ proc setColor*(text: PText, color: TColor) {. cdecl, importc: "sfText_setColor", dynlib: LibG.} proc getString*(text: PText): cstring {. cdecl, importc: "sfText_getString", dynlib: LibG.} -proc getUnicodeString*(text: PText): ptr Uint32 {.cdecl, +proc getUnicodeString*(text: PText): ptr uint32 {.cdecl, importc: "sfText_getUnicodeString", dynlib: LibG.} proc getFont*(text: PText): PFont {. cdecl, importc: "sfText_getFont", dynlib: LibG.} proc getCharacterSize*(text: PText): cint {. cdecl, importc: "sfText_getCharacterSize", dynlib: LibG.} -proc getStyle*(text: PText): Uint32 {. +proc getStyle*(text: PText): uint32 {. cdecl, importc: "sfText_getStyle", dynlib: LibG.} proc getColor*(text: PText): TColor {. cdecl, importc: "sfText_getColor", dynlib: LibG.} diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml_audio.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml_audio.nim index 3cfd33c02..5aa017ac4 100644 --- a/tests/manyloc/keineschweine/dependencies/sfml/sfml_audio.nim +++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml_audio.nim @@ -284,7 +284,7 @@ proc newSoundBuffer*(stream: PInputStream): PSoundBuffer{. #/ \brief Create a new sound buffer and load it from an array of samples in memory #/ #/ The assumed format of the audio samples is 16 bits signed integer -#/ (sfInt16). +#/ (sfint16). #/ #/ \param samples Pointer to the array of samples in memory #/ \param sampleCount Number of samples in the array @@ -334,7 +334,7 @@ proc saveToFile*(soundBuffer: PSoundBuffer; filename: cstring): bool {. #/ \brief Get the array of audio samples stored in a sound buffer #/ #/ The format of the returned samples is 16 bits signed integer -#/ (sfInt16). The total number of samples in this array +#/ (sfint16). The total number of samples in this array #/ is given by the sfSoundBuffer_getSampleCount function. #/ #/ \param soundBuffer Sound buffer object @@ -342,7 +342,7 @@ proc saveToFile*(soundBuffer: PSoundBuffer; filename: cstring): bool {. #/ \return Read-only pointer to the array of sound samples #/ #////////////////////////////////////////////////////////// -proc sfSoundBuffer_getSamples*(soundBuffer: PSoundBuffer): ptr Int16{. +proc sfSoundBuffer_getSamples*(soundBuffer: PSoundBuffer): ptr int16{. cdecl, importc: "sfSoundBuffer_getSamples", dynlib: Lib.} #////////////////////////////////////////////////////////// #/ \brief Get the number of samples stored in a sound buffer diff --git a/tests/manyloc/keineschweine/enet_server/enet_client.nim b/tests/manyloc/keineschweine/enet_server/enet_client.nim index 0c903a733..5ebbdb88b 100644 --- a/tests/manyloc/keineschweine/enet_server/enet_client.nim +++ b/tests/manyloc/keineschweine/enet_server/enet_client.nim @@ -105,6 +105,7 @@ proc tryLogin*(b: PButton) = passwd = u_passwd.getText()) dirServer.send HLogin, login proc tryTransition*(b: PButton) = + discard #zone.writePkt HZoneJoinReq, myCreds proc tryConnect*(b: PButton) = if not dirServer.connected: diff --git a/tests/manyloc/keineschweine/keineschweine.nim b/tests/manyloc/keineschweine/keineschweine.nim index e868b96a5..0a5dc1efc 100644 --- a/tests/manyloc/keineschweine/keineschweine.nim +++ b/tests/manyloc/keineschweine/keineschweine.nim @@ -143,7 +143,7 @@ proc mouseToSpace*(): TVector = proc explode*(b: PLiveBullet) ## TCollisionBeginFunc proc collisionBulletPlayer(arb: PArbiter; space: PSpace; - data: pointer): Bool{.cdecl.} = + data: pointer): bool{.cdecl.} = var bullet = cast[PLiveBullet](arb.a.data) target = cast[PVehicle](arb.b.data) @@ -152,7 +152,7 @@ proc collisionBulletPlayer(arb: PArbiter; space: PSpace; proc angularDampingSim(body: PBody, gravity: TVector, damping, dt: CpFloat){.cdecl.} = body.w -= (body.w * 0.98 * dt) - body.updateVelocity(gravity, damping, dt) + body.UpdateVelocity(gravity, damping, dt) proc initLevel() = loadAllAssets() @@ -227,7 +227,7 @@ proc explode*(b: PLiveBullet) = playSound(b.record.explosion.sound, b.body.getPos()) proc bulletUpdate(body: PBody, gravity: TVector, damping, dt: CpFloat){.cdecl.} = - body.updateVelocity(gravity, damping, dt) + body.UpdateVelocity(gravity, damping, dt) template getPhysical() {.immediate.} = result.body = space.addBody(newBody( @@ -237,7 +237,7 @@ template getPhysical() {.immediate.} = chipmunk.newCircleShape( result.body, record.physics.radius, - vectorZero)) + VectorZero)) proc newBullet*(record: PBulletRecord; fromPlayer: PPlayer): PLiveBullet = new(result, free) @@ -480,7 +480,7 @@ when defined(DebugKeys): echo(repr(activeVehicle.record)) elif keyPressed(KeyH): activeVehicle.body.setPos(vector(100.0, 100.0)) - activeVehicle.body.setVel(vectorZero) + activeVehicle.body.setVel(VectorZero) elif keyPressed(KeyComma): activeVehicle.body.setPos mouseToSpace()) ingameClient.registerHandler(KeyY, down, proc() = @@ -507,7 +507,7 @@ when defined(DebugKeys): return let body = shape.getBody() mouseJoint = space.addConstraint( - newPivotJoint(mouseBody, body, vectorZero, body.world2local(point))) + newPivotJoint(mouseBody, body, VectorZero, body.world2local(point))) mouseJoint.maxForce = 50000.0 mouseJoint.errorBias = pow(1.0 - 0.15, 60)) @@ -539,15 +539,15 @@ proc mainUpdate(dt: float) = elif not activeVehicle.isNil: if keyPressed(KeyUp): activeVehicle.accel(dt) - elif keyPressed(keyDown): + elif keyPressed(KeyDown): activeVehicle.reverse(dt) if keyPressed(KeyRight): activeVehicle.turn_right(dt) elif keyPressed(KeyLeft): activeVehicle.turn_left(dt) - if keyPressed(keyz): + if keyPressed(Keyz): activeVehicle.strafe_left(dt) - elif keyPressed(keyx): + elif keyPressed(Keyx): activeVehicle.strafe_right(dt) if keyPressed(KeyLControl): localPlayer.useItem 0 @@ -557,7 +557,7 @@ proc mainUpdate(dt: float) = localPlayer.useItem 2 if keyPressed(KeyW): localPlayer.useItem 3 - if Keypressed(keyA): + if keyPressed(KeyA): localPlayer.useItem 4 if keyPressed(sfml.KeyS): localPlayer.useItem 5 @@ -666,7 +666,7 @@ when isMainModule: import parseopt localPlayer = newPlayer() - LobbyInit() + lobbyInit() videoMode = getClientSettings().resolution window = newRenderWindow(videoMode, "sup", sfDefaultStyle) @@ -683,7 +683,7 @@ when isMainModule: mouseSprite.setOutlineThickness 1.4 mouseSprite.setOrigin vec2f(14, 14) - LobbyReady() + lobbyReady() playBtn = specGui.newButton( "Unspec - F12", position = vec2f(680.0, 8.0), onClick = proc(b: PButton) = toggleSpec()) diff --git a/tests/manyloc/keineschweine/lib/game_objects.nim b/tests/manyloc/keineschweine/lib/game_objects.nim index 37019ebcb..277ffb6cb 100644 --- a/tests/manyloc/keineschweine/lib/game_objects.nim +++ b/tests/manyloc/keineschweine/lib/game_objects.nim @@ -26,7 +26,7 @@ proc newObject*(record: PObjectRecord): PGameObject = when false: result.sprite = record.anim.spriteSheet.sprite.copy() result.body = newBody(result.record.physics.mass, 10.0) - result.shape = chipmunk.newCircleShape(result.body, result.record.physics.radius, vectorZero) + result.shape = chipmunk.newCircleShape(result.body, result.record.physics.radius, VectorZero) result.body.setPos(vector(100, 100)) proc newObject*(name: string): PGameObject = result = newObject(fetchObj(name)) diff --git a/tests/manyloc/keineschweine/lib/gl.nim b/tests/manyloc/keineschweine/lib/gl.nim index 9387b5bc9..c577f3404 100644 --- a/tests/manyloc/keineschweine/lib/gl.nim +++ b/tests/manyloc/keineschweine/lib/gl.nim @@ -38,7 +38,7 @@ type PGLclampf* = ptr TGLclampf PGLdouble* = ptr TGLdouble PGLclampd* = ptr TGLclampd - PGLvoid* = Pointer + PGLvoid* = pointer PPGLvoid* = ptr PGLvoid TGLenum* = cint TGLboolean* = bool @@ -983,7 +983,7 @@ const # Version GL_TEXTURE_COMPONENTS* = GL_TEXTURE_INTERNAL_FORMAT proc glAccum*(op: TGLenum, value: TGLfloat){.dynlib: dllname, importc: "glAccum".} -proc glAlphaFunc*(func: TGLenum, theref: TGLclampf){.dynlib: dllname, +proc glAlphaFunc*(fun: TGLenum, theref: TGLclampf){.dynlib: dllname, importc: "glAlphaFunc".} proc glAreTexturesResident*(n: TGLsizei, textures: PGLuint, residences: PGLboolean): TGLboolean{. @@ -998,7 +998,7 @@ proc glBitmap*(width, height: TGLsizei, xorig, yorig: TGLfloat, proc glBlendFunc*(sfactor, dfactor: TGLenum){.dynlib: dllname, importc: "glBlendFunc".} proc glCallList*(list: TGLuint){.dynlib: dllname, importc: "glCallList".} -proc glCallLists*(n: TGLsizei, atype: TGLenum, lists: Pointer){.dynlib: dllname, +proc glCallLists*(n: TGLsizei, atype: TGLenum, lists: pointer){.dynlib: dllname, importc: "glCallLists".} proc glClear*(mask: TGLbitfield){.dynlib: dllname, importc: "glClear".} proc glClearAccum*(red, green, blue, alpha: TGLfloat){.dynlib: dllname, @@ -1062,7 +1062,7 @@ proc glColorMask*(red, green, blue, alpha: TGLboolean){.dynlib: dllname, proc glColorMaterial*(face, mode: TGLenum){.dynlib: dllname, importc: "glColorMaterial".} proc glColorPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei, - pointer: Pointer){.dynlib: dllname, + p: pointer){.dynlib: dllname, importc: "glColorPointer".} proc glCopyPixels*(x, y: TGLint, width, height: TGLsizei, atype: TGLenum){. dynlib: dllname, importc: "glCopyPixels".} @@ -1084,7 +1084,7 @@ proc glDeleteLists*(list: TGLuint, range: TGLsizei){.dynlib: dllname, importc: "glDeleteLists".} proc glDeleteTextures*(n: TGLsizei, textures: PGLuint){.dynlib: dllname, importc: "glDeleteTextures".} -proc glDepthFunc*(func: TGLenum){.dynlib: dllname, importc: "glDepthFunc".} +proc glDepthFunc*(fun: TGLenum){.dynlib: dllname, importc: "glDepthFunc".} proc glDepthMask*(flag: TGLboolean){.dynlib: dllname, importc: "glDepthMask".} proc glDepthRange*(zNear, zFar: TGLclampd){.dynlib: dllname, importc: "glDepthRange".} @@ -1095,12 +1095,12 @@ proc glDrawArrays*(mode: TGLenum, first: TGLint, count: TGLsizei){. dynlib: dllname, importc: "glDrawArrays".} proc glDrawBuffer*(mode: TGLenum){.dynlib: dllname, importc: "glDrawBuffer".} proc glDrawElements*(mode: TGLenum, count: TGLsizei, atype: TGLenum, - indices: Pointer){.dynlib: dllname, + indices: pointer){.dynlib: dllname, importc: "glDrawElements".} proc glDrawPixels*(width, height: TGLsizei, format, atype: TGLenum, - pixels: Pointer){.dynlib: dllname, importc: "glDrawPixels".} + pixels: pointer){.dynlib: dllname, importc: "glDrawPixels".} proc glEdgeFlag*(flag: TGLboolean){.dynlib: dllname, importc: "glEdgeFlag".} -proc glEdgeFlagPointer*(stride: TGLsizei, pointer: Pointer){.dynlib: dllname, +proc glEdgeFlagPointer*(stride: TGLsizei, p: pointer){.dynlib: dllname, importc: "glEdgeFlagPointer".} proc glEdgeFlagv*(flag: PGLboolean){.dynlib: dllname, importc: "glEdgeFlagv".} proc glEnable*(cap: TGLenum){.dynlib: dllname, importc: "glEnable".} @@ -1171,7 +1171,7 @@ proc glGetPixelMapuiv*(map: TGLenum, values: PGLuint){.dynlib: dllname, importc: "glGetPixelMapuiv".} proc glGetPixelMapusv*(map: TGLenum, values: PGLushort){.dynlib: dllname, importc: "glGetPixelMapusv".} -proc glGetPointerv*(pname: TGLenum, params: Pointer){.dynlib: dllname, +proc glGetPointerv*(pname: TGLenum, params: pointer){.dynlib: dllname, importc: "glGetPointerv".} proc glGetPolygonStipple*(mask: PGLubyte){.dynlib: dllname, importc: "glGetPolygonStipple".} @@ -1188,10 +1188,10 @@ proc glGetTexGenfv*(coord, pname: TGLenum, params: PGLfloat){.dynlib: dllname, proc glGetTexGeniv*(coord, pname: TGLenum, params: PGLint){.dynlib: dllname, importc: "glGetTexGeniv".} proc glGetTexImage*(target: TGLenum, level: TGLint, format: TGLenum, - atype: TGLenum, pixels: Pointer){.dynlib: dllname, + atype: TGLenum, pixels: pointer){.dynlib: dllname, importc: "glGetTexImage".} proc glGetTexLevelParameterfv*(target: TGLenum, level: TGLint, pname: TGLenum, - params: Pointer){.dynlib: dllname, + params: pointer){.dynlib: dllname, importc: "glGetTexLevelParameterfv".} proc glGetTexLevelParameteriv*(target: TGLenum, level: TGLint, pname: TGLenum, params: PGLint){.dynlib: dllname, @@ -1202,7 +1202,7 @@ proc glGetTexParameteriv*(target, pname: TGLenum, params: PGLint){. dynlib: dllname, importc: "glGetTexParameteriv".} proc glHint*(target, mode: TGLenum){.dynlib: dllname, importc: "glHint".} proc glIndexMask*(mask: TGLuint){.dynlib: dllname, importc: "glIndexMask".} -proc glIndexPointer*(atype: TGLenum, stride: TGLsizei, pointer: Pointer){. +proc glIndexPointer*(atype: TGLenum, stride: TGLsizei, p: pointer){. dynlib: dllname, importc: "glIndexPointer".} proc glIndexd*(c: TGLdouble){.dynlib: dllname, importc: "glIndexd".} proc glIndexdv*(c: PGLdouble){.dynlib: dllname, importc: "glIndexdv".} @@ -1215,7 +1215,7 @@ proc glIndexsv*(c: PGLshort){.dynlib: dllname, importc: "glIndexsv".} proc glIndexub*(c: TGLubyte){.dynlib: dllname, importc: "glIndexub".} proc glIndexubv*(c: PGLubyte){.dynlib: dllname, importc: "glIndexubv".} proc glInitNames*(){.dynlib: dllname, importc: "glInitNames".} -proc glInterleavedArrays*(format: TGLenum, stride: TGLsizei, pointer: Pointer){. +proc glInterleavedArrays*(format: TGLenum, stride: TGLsizei, p: pointer){. dynlib: dllname, importc: "glInterleavedArrays".} proc glIsEnabled*(cap: TGLenum): TGLboolean{.dynlib: dllname, importc: "glIsEnabled".} @@ -1288,7 +1288,7 @@ proc glNormal3i*(nx, ny, nz: TGLint){.dynlib: dllname, importc: "glNormal3i".} proc glNormal3iv*(v: PGLint){.dynlib: dllname, importc: "glNormal3iv".} proc glNormal3s*(nx, ny, nz: TGLshort){.dynlib: dllname, importc: "glNormal3s".} proc glNormal3sv*(v: PGLshort){.dynlib: dllname, importc: "glNormal3sv".} -proc glNormalPointer*(atype: TGLenum, stride: TGLsizei, pointer: Pointer){. +proc glNormalPointer*(atype: TGLenum, stride: TGLsizei, p: pointer){. dynlib: dllname, importc: "glNormalPointer".} proc glOrtho*(left, right, bottom, top, zNear, zFar: TGLdouble){. dynlib: dllname, importc: "glOrtho".} @@ -1360,7 +1360,7 @@ proc glRasterPos4s*(x, y, z, w: TGLshort){.dynlib: dllname, proc glRasterPos4sv*(v: PGLshort){.dynlib: dllname, importc: "glRasterPos4sv".} proc glReadBuffer*(mode: TGLenum){.dynlib: dllname, importc: "glReadBuffer".} proc glReadPixels*(x, y: TGLint, width, height: TGLsizei, - format, atype: TGLenum, pixels: Pointer){.dynlib: dllname, + format, atype: TGLenum, pixels: pointer){.dynlib: dllname, importc: "glReadPixels".} proc glRectd*(x1, y1, x2, y2: TGLdouble){.dynlib: dllname, importc: "glRectd".} proc glRectdv*(v1: PGLdouble, v2: PGLdouble){.dynlib: dllname, @@ -1383,7 +1383,7 @@ proc glScissor*(x, y: TGLint, width, height: TGLsizei){.dynlib: dllname, proc glSelectBuffer*(size: TGLsizei, buffer: PGLuint){.dynlib: dllname, importc: "glSelectBuffer".} proc glShadeModel*(mode: TGLenum){.dynlib: dllname, importc: "glShadeModel".} -proc glStencilFunc*(func: TGLenum, theref: TGLint, mask: TGLuint){. +proc glStencilFunc*(fun: TGLenum, theref: TGLint, mask: TGLuint){. dynlib: dllname, importc: "glStencilFunc".} proc glStencilMask*(mask: TGLuint){.dynlib: dllname, importc: "glStencilMask".} proc glStencilOp*(fail, zfail, zpass: TGLenum){.dynlib: dllname, @@ -1424,7 +1424,7 @@ proc glTexCoord4s*(s, t, r, q: TGLshort){.dynlib: dllname, importc: "glTexCoord4s".} proc glTexCoord4sv*(v: PGLshort){.dynlib: dllname, importc: "glTexCoord4sv".} proc glTexCoordPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei, - pointer: Pointer){.dynlib: dllname, + p: pointer){.dynlib: dllname, importc: "glTexCoordPointer".} proc glTexEnvf*(target: TGLenum, pname: TGLenum, param: TGLfloat){. dynlib: dllname, importc: "glTexEnvf".} @@ -1448,10 +1448,10 @@ proc glTexGeniv*(coord: TGLenum, pname: TGLenum, params: PGLint){. dynlib: dllname, importc: "glTexGeniv".} proc glTexImage1D*(target: TGLenum, level, internalformat: TGLint, width: TGLsizei, border: TGLint, format, atype: TGLenum, - pixels: Pointer){.dynlib: dllname, importc: "glTexImage1D".} + pixels: pointer){.dynlib: dllname, importc: "glTexImage1D".} proc glTexImage2D*(target: TGLenum, level, internalformat: TGLint, width, height: TGLsizei, border: TGLint, - format, atype: TGLenum, pixels: Pointer){.dynlib: dllname, + format, atype: TGLenum, pixels: pointer){.dynlib: dllname, importc: "glTexImage2D".} proc glTexParameterf*(target: TGLenum, pname: TGLenum, param: TGLfloat){. dynlib: dllname, importc: "glTexParameterf".} @@ -1462,11 +1462,11 @@ proc glTexParameteri*(target: TGLenum, pname: TGLenum, param: TGLint){. proc glTexParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){. dynlib: dllname, importc: "glTexParameteriv".} proc glTexSubImage1D*(target: TGLenum, level, xoffset: TGLint, width: TGLsizei, - format, atype: TGLenum, pixels: Pointer){.dynlib: dllname, + format, atype: TGLenum, pixels: pointer){.dynlib: dllname, importc: "glTexSubImage1D".} proc glTexSubImage2D*(target: TGLenum, level, xoffset, yoffset: TGLint, width, height: TGLsizei, format, atype: TGLenum, - pixels: Pointer){.dynlib: dllname, + pixels: pointer){.dynlib: dllname, importc: "glTexSubImage2D".} proc glTranslated*(x, y, z: TGLdouble){.dynlib: dllname, importc: "glTranslated".} proc glTranslatef*(x, y, z: TGLfloat){.dynlib: dllname, importc: "glTranslatef".} @@ -1495,7 +1495,7 @@ proc glVertex4iv*(v: PGLint){.dynlib: dllname, importc: "glVertex4iv".} proc glVertex4s*(x, y, z, w: TGLshort){.dynlib: dllname, importc: "glVertex4s".} proc glVertex4sv*(v: PGLshort){.dynlib: dllname, importc: "glVertex4sv".} proc glVertexPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei, - pointer: Pointer){.dynlib: dllname, + p: pointer){.dynlib: dllname, importc: "glVertexPointer".} proc glViewport*(x, y: TGLint, width, height: TGLsizei){.dynlib: dllname, importc: "glViewport".} @@ -1505,28 +1505,28 @@ type count: TGLsizei) PFN_GLVERTEX_POINTER_EXTPROC* = proc (size: TGLint, atype: TGLenum, stride, count: TGLsizei, - pointer: Pointer) + p: pointer) PFN_GLNORMAL_POINTER_EXTPROC* = proc (atype: TGLenum, stride, count: TGLsizei, - pointer: Pointer) + p: pointer) PFN_GLCOLOR_POINTER_EXTPROC* = proc (size: TGLint, atype: TGLenum, - stride, count: TGLsizei, pointer: Pointer) + stride, count: TGLsizei, p: pointer) PFN_GLINDEX_POINTER_EXTPROC* = proc (atype: TGLenum, stride, count: TGLsizei, - pointer: Pointer) + p: pointer) PFN_GLTEXCOORD_POINTER_EXTPROC* = proc (size: TGLint, atype: TGLenum, - stride, count: TGLsizei, pointer: Pointer) + stride, count: TGLsizei, p: pointer) PFN_GLEDGEFLAG_POINTER_EXTPROC* = proc (stride, count: TGLsizei, pointer: PGLboolean) - PFN_GLGET_POINTER_VEXT_PROC* = proc (pname: TGLenum, params: Pointer) + PFN_GLGET_POINTER_VEXT_PROC* = proc (pname: TGLenum, params: pointer) PFN_GLARRAY_ELEMENT_ARRAY_EXTPROC* = proc (mode: TGLenum, count: TGLsizei, - pi: Pointer) # WIN_swap_hint + pi: pointer) # WIN_swap_hint PFN_GLADDSWAPHINT_RECT_WINPROC* = proc (x, y: TGLint, width, height: TGLsizei) PFN_GLCOLOR_TABLE_EXTPROC* = proc (target, internalFormat: TGLenum, width: TGLsizei, format, atype: TGLenum, - data: Pointer) + data: pointer) PFN_GLCOLOR_SUBTABLE_EXTPROC* = proc (target: TGLenum, start, count: TGLsizei, - format, atype: TGLenum, data: Pointer) + format, atype: TGLenum, data: pointer) PFN_GLGETCOLOR_TABLE_EXTPROC* = proc (target, format, atype: TGLenum, - data: Pointer) + data: pointer) PFN_GLGETCOLOR_TABLE_PARAMETER_IVEXTPROC* = proc (target, pname: TGLenum, params: PGLint) PFN_GLGETCOLOR_TABLE_PARAMETER_FVEXTPROC* = proc (target, pname: TGLenum, diff --git a/tests/manyloc/keineschweine/lib/map_filter.nim b/tests/manyloc/keineschweine/lib/map_filter.nim index 54173fa61..966b84b6a 100644 --- a/tests/manyloc/keineschweine/lib/map_filter.nim +++ b/tests/manyloc/keineschweine/lib/map_filter.nim @@ -4,14 +4,14 @@ template filterIt2*(seq, pred: expr, body: stmt): stmt {.immediate, dirty.} = for it in items(seq): if pred: body -proc map*[A, B](x: seq[A], func: proc(y: A): B {.closure.}): seq[B] = +proc map*[A, B](x: seq[A], fun: proc(y: A): B {.closure.}): seq[B] = result = @[] for item in x.items: - result.add func(item) + result.add fun(item) -proc mapInPlace*[A](x: var seq[A], func: proc(y: A): A {.closure.}) = +proc mapInPlace*[A](x: var seq[A], fun: proc(y: A): A {.closure.}) = for i in 0..x.len-1: - x[i] = func(x[i]) + x[i] = fun(x[i]) template unless*(condition: expr; body: stmt): stmt {.dirty.} = if not(condition): @@ -38,4 +38,4 @@ when isMainModule: var someSeq = @[9,8,7,6,5,4,3,2,1] ## numbers < 6 or even filterIt2 someSeq, it < 6 or (it and 1) == 0: echo(it) - echo "-----------" \ No newline at end of file + echo "-----------" diff --git a/tests/manyloc/keineschweine/lib/sg_assets.nim b/tests/manyloc/keineschweine/lib/sg_assets.nim index ccd1d9280..c5a39550a 100644 --- a/tests/manyloc/keineschweine/lib/sg_assets.nim +++ b/tests/manyloc/keineschweine/lib/sg_assets.nim @@ -122,9 +122,9 @@ var nameToBulletID*: TTable[string, int] activeState = Lobby -proc newSprite(filename: string; errors: var seq[string]): PSpriteSheet +proc newSprite*(filename: string; errors: var seq[string]): PSpriteSheet proc load*(ss: PSpriteSheet): bool {.discardable.} -proc newSound(filename: string; errors: var seq[string]): PSoundRecord +proc newSound*(filename: string; errors: var seq[string]): PSoundRecord proc load*(s: PSoundRecord): bool {.discardable.} proc validateSettings*(settings: PJsonNode; errors: var seq[string]): bool @@ -146,7 +146,7 @@ proc importHandling(data: PJsonNode): THandlingRecord proc importBullet(data: PJsonNode; errors: var seq[string]): PBulletRecord proc importSoul(data: PJsonNode): TSoulRecord proc importExplosion(data: PJsonNode; errors: var seq[string]): TExplosionRecord -proc importSound(data: PJsonNode; errors: var seq[string]; fieldName: string = nil): PSoundRecord +proc importSound*(data: PJsonNode; errors: var seq[string]; fieldName: string = nil): PSoundRecord ## this is the only pipe between lobby and main.nim proc getActiveState*(): TGameState = @@ -466,7 +466,7 @@ proc importPhys(data: PJsonNode): TPhysicsRecord = phys.getField("radius", result.radius) phys.getField("mass", result.mass) when not defined(NoChipmunk): - result.moment = momentForCircle(result.mass, 0.0, result.radius, vectorZero) * MomentMult + result.moment = momentForCircle(result.mass, 0.0, result.radius, VectorZero) * MomentMult proc importHandling(data: PJsonNode): THandlingRecord = result.thrust = 45.0 result.topSpeed = 100.0 #unused diff --git a/tests/manyloc/keineschweine/lib/sg_packets.nim b/tests/manyloc/keineschweine/lib/sg_packets.nim index 625436cb6..601054b47 100644 --- a/tests/manyloc/keineschweine/lib/sg_packets.nim +++ b/tests/manyloc/keineschweine/lib/sg_packets.nim @@ -9,8 +9,8 @@ template idpacket(pktName, id, s2c, c2s: expr): stmt {.immediate, dirty.} = defPacket(`Sc pktName`, s2c) defPacket(`Cs pktName`, c2s) -forwardPacketT(Uint8, int8) -forwardPacketT(Uint16, int16) +forwardPacketT(uint8, int8) +forwardPacketT(uint16, int16) forwardPacketT(TPort, int16) idPacket(Login, 'a', @@ -51,7 +51,7 @@ defPacket(ScTeamList, tuple[teams: seq[ScTeam]]) let HTeamChange* = 't' idPacket(ZoneQuery, 'Q', - tuple[playerCount: Uint16], ##i should include a time here or something + tuple[playerCount: uint16], ##i should include a time here or something tuple[pad: char = '\0']) type SpawnKind = enum diff --git a/tests/manyloc/keineschweine/lib/vehicles.nim b/tests/manyloc/keineschweine/lib/vehicles.nim index edbd84ff9..4b11856c6 100644 --- a/tests/manyloc/keineschweine/lib/vehicles.nim +++ b/tests/manyloc/keineschweine/lib/vehicles.nim @@ -9,22 +9,22 @@ proc accel*(obj: PVehicle, dt: float) = # sin(obj.angle) * obj.record.handling.thrust.float * dt) obj.body.applyImpulse( vectorForAngle(obj.body.getAngle()) * dt * obj.record.handling.thrust, - vectorZero) + VectorZero) proc reverse*(obj: PVehicle, dt: float) = #obj.velocity += vec2f( # -cos(obj.angle) * obj.record.handling.reverse.float * dt, # -sin(obj.angle) * obj.record.handling.reverse.float * dt) obj.body.applyImpulse( -vectorForAngle(obj.body.getAngle()) * dt * obj.record.handling.reverse, - vectorZero) + VectorZero) proc strafe_left*(obj: PVehicle, dt: float) = obj.body.applyImpulse( vectorForAngle(obj.body.getAngle()).perp() * obj.record.handling.strafe * dt, - vectorZero) + VectorZero) proc strafe_right*(obj: PVehicle, dt: float) = obj.body.applyImpulse( vectorForAngle(obj.body.getAngle()).rperp()* obj.record.handling.strafe * dt, - vectorZero) + VectorZero) proc turn_right*(obj: PVehicle, dt: float) = #obj.angle = (obj.angle + (obj.record.handling.rotation.float / 10.0 * dt)) mod TAU obj.body.setTorque(obj.record.handling.rotation) diff --git a/tests/modules/tmismatchedvisibility.nim b/tests/modules/tmismatchedvisibility.nim index 6f2f79282..325c729c0 100644 --- a/tests/modules/tmismatchedvisibility.nim +++ b/tests/modules/tmismatchedvisibility.nim @@ -1,9 +1,9 @@ discard """ line: 8 - errormsg: "public implementation 'tmismatchedvisibility.foo(a: int): int' has non-public forward declaration in tmismatchedvisibility.nim(6,5)" + errormsg: "public implementation 'tmismatchedvisibility.foo(a: int)' has non-public forward declaration in " """ proc foo(a: int): int proc foo*(a: int): int = - result = a + a \ No newline at end of file + result = a + a diff --git a/tests/osproc/tstdin.nim b/tests/osproc/tstdin.nim index 2ea939992..b491c2500 100644 --- a/tests/osproc/tstdin.nim +++ b/tests/osproc/tstdin.nim @@ -4,13 +4,16 @@ discard """ """ import osproc, os, streams -doAssert fileExists(getCurrentDir() / "tests" / "osproc" / "ta.exe") +const filename = when defined(Windows): "ta.exe" else: "ta" -var p = startProcess("ta.exe", getCurrentDir() / "tests" / "osproc") +doAssert fileExists(getCurrentDir() / "tests" / "osproc" / filename) + +var p = startProcess(filename, getCurrentDir() / "tests" / "osproc") p.inputStream.write("5\n") +p.inputStream.flush() while true: let line = p.outputStream.readLine() if line != "": echo line else: - break \ No newline at end of file + break diff --git a/tests/static/tmatrix.nim b/tests/static/tmatrix.nim new file mode 100644 index 000000000..a143e2bc9 --- /dev/null +++ b/tests/static/tmatrix.nim @@ -0,0 +1,19 @@ +discard """ + output: "" +""" + +type Matrix[M,N: static[int]] = array[M, array[N, float]] + +let a = [[1.0, 1.0, 1.0, 1.0], + [2.0, 4.0, 8.0, 16.0], + [3.0, 9.0, 27.0, 81.0], + [4.0, 16.0, 64.0, 256.0]] + +proc `$`(m: Matrix): string = + result = "" + +proc `*`[M,N,M2,N2](a: Matrix[M,N2]; b: Matrix[M2,N]): Matrix[M,N] = + discard + +echo a * a + diff --git a/tests/stdlib/tdialogs.nim b/tests/stdlib/tdialogs.nim index d161a976d..f0203d319 100644 --- a/tests/stdlib/tdialogs.nim +++ b/tests/stdlib/tdialogs.nim @@ -4,7 +4,7 @@ import dialogs, gtk2 gtk2.nimrod_init() -var x = ChooseFilesToOpen(nil) +var x = chooseFilesToOpen(nil) for a in items(x): writeln(stdout, a) @@ -12,6 +12,6 @@ info(nil, "start with an info box") warning(nil, "now a warning ...") error(nil, "... and an error!") -writeln(stdout, ChooseFileToOpen(nil)) -writeln(stdout, ChooseFileToSave(nil)) -writeln(stdout, ChooseDir(nil)) +writeln(stdout, chooseFileToOpen(nil)) +writeln(stdout, chooseFileToSave(nil)) +writeln(stdout, chooseDir(nil)) diff --git a/tests/stdlib/tgetfileinfo.nim b/tests/stdlib/tgetfileinfo.nim index 49a019061..c8e496cc1 100644 --- a/tests/stdlib/tgetfileinfo.nim +++ b/tests/stdlib/tgetfileinfo.nim @@ -32,7 +32,7 @@ proc caseOneAndTwo(followLink: bool) = try: discard getFileInfo(getAppFilename(), followLink) #echo("String : Existing File : Symlink $# : Success" % $followLink) - except EOS: + except OSError: echo("String : Existing File : Symlink $# : Failure" % $followLink) proc caseThreeAndFour(followLink: bool) = @@ -40,7 +40,8 @@ proc caseThreeAndFour(followLink: bool) = try: discard getFileInfo(invalidName, true) echo("String : Non-existing File : Symlink $# : Failure" % $followLink) - except EOS: + except OSError: + discard #echo("String : Non-existing File : Symlink $# : Success" % $followLink) proc testGetFileInfo = @@ -82,12 +83,14 @@ proc testGetFileInfo = discard getFileInfo(testFile) echo("Handle : Invalid File : Failure") except EIO, EOS: + discard #echo("Handle : Invalid File : Success") try: discard getFileInfo(testHandle) echo("Handle : Invalid File : Failure") except EIO, EOS: + discard #echo("Handle : Invalid File : Success") -testGetFileInfo() \ No newline at end of file +testGetFileInfo() diff --git a/tests/stdlib/tircbot.nim b/tests/stdlib/tircbot.nim index b91300762..6b209dce3 100644 --- a/tests/stdlib/tircbot.nim +++ b/tests/stdlib/tircbot.nim @@ -2,7 +2,7 @@ import irc, sockets, asyncio, json, os, strutils, times, redis type TDb* = object - r*: TRedis + r*: Redis lastPing: float TBuildResult* = enum @@ -15,20 +15,20 @@ type TCommit* = object commitMsg*, username*, hash*: string - date*: TTime + date*: Time TPlatform* = object buildResult*: TBuildResult testResult*: TTestResult failReason*, platform*: string - total*, passed*, skipped*, failed*: biggestInt + total*, passed*, skipped*, failed*: BiggestInt csources*: bool const listName = "commits" - failOnExisting = False + failOnExisting = false -proc open*(host = "localhost", port: TPort): TDb = +proc open*(host = "localhost", port: Port): TDb = result.r = redis.open(host, port) result.lastPing = epochTime() @@ -80,7 +80,7 @@ proc getCommits*(database: TDb, for key, value in database.r.hPairs(c): case normalize(key) of "commitmsg": commit.commitMsg = value - of "date": commit.date = TTime(parseInt(value)) + of "date": commit.date = Time(parseInt(value)) of "username": commit.username = value else: echo(key) @@ -157,21 +157,21 @@ proc `[]`*(p: seq[TPlatform], name: string): TPlatform = for platform in items(p): if platform.platform == name: return platform - raise newException(EInvalidValue, name & " platforms not found in commits.") + raise newException(ValueError, name & " platforms not found in commits.") proc contains*(p: seq[TPlatform], s: string): bool = for i in items(p): if i.platform == s: - return True + return true type PState = ref TState - TState = object of TObject - dispatcher: PDispatcher - sock: PAsyncSocket + TState = object of RootObj + dispatcher: Dispatcher + sock: AsyncSocket ircClient: PAsyncIRC - hubPort: TPort + hubPort: Port database: TDb dbConnected: bool @@ -181,7 +181,7 @@ type TSeen = object nick: string channel: string - timestamp: TTime + timestamp: Time case kind*: TSeenType of PSeenJoin: nil of PSeenPart, PSeenQuit, PSeenMsg: @@ -218,11 +218,12 @@ proc getSeen(d: TDb, nick: string, s: var TSeen): bool = for key, value in d.r.hPairs("seen:" & nick): case normalize(key) of "type": + discard #s.kind = value.parseInt.TSeenType of "channel": s.channel = value of "timestamp": - s.timestamp = TTime(value.parseInt) + s.timestamp = Time(value.parseInt) of "msg": s.msg = value of "newnick": @@ -235,7 +236,7 @@ template createSeen(typ: TSeenType, n, c: string): stmt {.immediate, dirty.} = seenNick.channel = c seenNick.timestamp = getTime() -proc parseReply(line: string, expect: string): Bool = +proc parseReply(line: string, expect: string): bool = var jsonDoc = parseJson(line) return jsonDoc["reply"].str == expect @@ -272,14 +273,14 @@ proc handleWebMessage(state: PState, line: string) = message.add(limitCommitMsg(commit["message"].str)) # Send message to #nim. - state.ircClient.privmsg(joinChans[0], message) + discard state.ircClient.privmsg(joinChans[0], message) elif json.hasKey("redisinfo"): assert json["redisinfo"].hasKey("port") #let redisPort = json["redisinfo"]["port"].num state.dbConnected = true proc hubConnect(state: PState) -proc handleConnect(s: PAsyncSocket, state: PState) = +proc handleConnect(s: AsyncSocket, state: PState) = try: # Send greeting var obj = newJObject() @@ -295,7 +296,7 @@ proc handleConnect(s: PAsyncSocket, state: PState) = doAssert parseReply(line, "OK") echo("The hub accepted me!") else: - raise newException(EInvalidValue, + raise newException(ValueError, "Hub didn't accept me. Waited 1.5 seconds.") # ask for the redis info @@ -303,35 +304,35 @@ proc handleConnect(s: PAsyncSocket, state: PState) = riobj["do"] = newJString("redisinfo") state.sock.send($riobj & "\c\L") - except EOS: + except OsError: echo(getCurrentExceptionMsg()) s.close() echo("Waiting 5 seconds...") sleep(5000) state.hubConnect() -proc handleRead(s: PAsyncSocket, state: PState) = +proc handleRead(s: AsyncSocket, state: PState) = var line = "" if state.sock.recvLine(line): if line != "": # Handle the message state.handleWebMessage(line) else: - echo("Disconnected from hub: ", OSErrorMsg()) + echo("Disconnected from hub: ", osErrorMsg()) s.close() echo("Reconnecting...") state.hubConnect() else: - echo(OSErrorMsg()) + echo(osErrorMsg()) proc hubConnect(state: PState) = - state.sock = AsyncSocket() + state.sock = asyncSocket() state.sock.connect("127.0.0.1", state.hubPort) state.sock.handleConnect = - proc (s: PAsyncSocket) = + proc (s: AsyncSocket) = handleConnect(s, state) state.sock.handleRead = - proc (s: PAsyncSocket) = + proc (s: AsyncSocket) = handleRead(s, state) state.dispatcher.register(state.sock) @@ -426,7 +427,7 @@ proc handleIrc(irc: PAsyncIRC, event: TIRCEvent, state: PState) = else: discard # TODO: ? -proc open(port: TPort = TPort(5123)): PState = +proc open(port: Port = Port(5123)): PState = var res: PState new(res) res.dispatcher = newDispatcher() diff --git a/tests/stdlib/tmitems.nim b/tests/stdlib/tmitems.nim index 2297f0ee9..bf67d2b7b 100644 --- a/tests/stdlib/tmitems.nim +++ b/tests/stdlib/tmitems.nim @@ -12,7 +12,7 @@ fpqeew [11, 12, 13] [11, 12, 13] { "key1": 11, "key2": 12, "key3": 13} -[ 11, 12, 13] +[11, 12, 13] <Students> <Student Name="Aprilfoo" /> <Student Name="bar" /> diff --git a/tests/stdlib/tpermutations.nim b/tests/stdlib/tpermutations.nim new file mode 100644 index 000000000..a6e07ded6 --- /dev/null +++ b/tests/stdlib/tpermutations.nim @@ -0,0 +1,19 @@ +discard """ + output: '''@[0, 2, 1] +@[1, 0, 2] +@[1, 2, 0] +@[2, 0, 1] +@[2, 1, 0] +@[2, 0, 1] +@[1, 2, 0] +@[1, 0, 2] +@[0, 2, 1] +@[0, 1, 2]''' +""" +import algorithm + +var v = @[0, 1, 2] +while v.nextPermutation(): + echo v +while v.prevPermutation(): + echo v diff --git a/tests/template/t2do.nim b/tests/template/t2do.nim new file mode 100644 index 000000000..b87e3328c --- /dev/null +++ b/tests/template/t2do.nim @@ -0,0 +1,22 @@ +discard """ + output: "8.0" +""" + +# bug #2057 + +proc mpf_get_d(x: int): float = float(x) +proc mpf_cmp_d(a: int; b: float): int = 0 + +template toFloatHelper(result: expr; tooSmall, tooLarge: stmt) {.immediate.} = + result = mpf_get_d(a) + if result == 0.0 and mpf_cmp_d(a,0.0) != 0: + tooSmall + if result == Inf: + tooLarge + +proc toFloat*(a: int): float = + toFloatHelper(result) + do: raise newException(ValueError, "number too small"): + raise newException(ValueError, "number too large") + +echo toFloat(8) diff --git a/tests/template/tparams_gensymed.nim b/tests/template/tparams_gensymed.nim index 4178812af..33940874d 100644 --- a/tests/template/tparams_gensymed.nim +++ b/tests/template/tparams_gensymed.nim @@ -12,3 +12,22 @@ template genNodeKind(kind, name: expr): stmt = result.add(c) genNodeKind(nnkNone, None) + + +# Test that generics in templates still work (regression to fix #1915) + +# bug #2004 + +type Something = object + +proc testA(x: Something) = discard + +template def(name: expr) {.immediate.} = + proc testB[T](reallyUniqueName: T) = + `test name`(reallyUniqueName) +def A + +var x: Something +testB(x) + + diff --git a/tests/template/tscope.nim b/tests/template/tscope.nim new file mode 100644 index 000000000..2d5841af3 --- /dev/null +++ b/tests/template/tscope.nim @@ -0,0 +1,12 @@ +discard """ + errormsg: "redefinition of 'x'" +""" + +var x = 1 +template quantity(): stmt {.immediate.} = + # Causes internal error in compiler/sem.nim + proc unit*(x = 1.0): float = 12 + # Throws the correct error: redefinition of 'x' + #proc unit*(y = 1.0): float = 12 +quantity() +var x = 2 diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim index 5cd5c1545..54e962693 100644 --- a/tests/testament/categories.nim +++ b/tests/testament/categories.nim @@ -330,8 +330,9 @@ proc `&?.`(a, b: string): string = proc processCategory(r: var TResults, cat: Category, options: string) = case cat.string.normalize of "rodfiles": - compileRodFiles(r, cat, options) - runRodFiles(r, cat, options) + discard # Disabled for now + #compileRodFiles(r, cat, options) + #runRodFiles(r, cat, options) of "js": # XXX JS doesn't need to be special anymore jsTests(r, cat, options) diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim index 865ba9c75..45643be10 100644 --- a/tests/testament/tester.nim +++ b/tests/testament/tester.nim @@ -134,7 +134,7 @@ proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest) = proc generatedFile(path, name: string, target: TTarget): string = let ext = targetToExt[target] result = path / "nimcache" / - (if target == targetJS: path.splitPath.tail & "_" else: "") & + (if target == targetJS: path.splitPath.tail & "_" else: "compiler_") & name.changeFileExt(ext) proc codegenCheck(test: TTest, check: string, given: var TSpec) = diff --git a/tests/vm/tconsttable.nim b/tests/vm/tconsttable.nim new file mode 100644 index 000000000..64a74a59d --- /dev/null +++ b/tests/vm/tconsttable.nim @@ -0,0 +1,19 @@ +discard """ + output: '''is +finally +nice!''' +""" + +import tables + +const + foo = {"ah": "finally", "this": "is", "possible.": "nice!"}.toTable() + +# protect against overly smart compiler: +var x = "this" + +echo foo[x] +x = "ah" +echo foo[x] +x = "possible." +echo foo[x] diff --git a/todo.txt b/todo.txt index d64f4fdd4..252699bf1 100644 --- a/todo.txt +++ b/todo.txt @@ -1,11 +1,20 @@ -version 0.10 -============ +version 0.10.4 +============== + +- make 'nil' work for 'add' and 'len' +- improve GC-unsafety warnings +- get rid of 'mget'; aka priority of 'var' needs to be 'var{lvalue}' +- improve documentation (theindex!) +- fix the getUniqueType() bug + + +version 1.0 +=========== - nimsuggest: auto-completion needs to work in 'class' macros - improve the docs for inheritance - The bitwise 'not' operator will be renamed to 'bnot' to prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs! -- parameter lists without type end up in 'experimental' - iterators always require a return type - overloading of '=' @@ -25,7 +34,6 @@ Low priority: - support for exception propagation? (hard to implement) - the copying of the 'ref Promise' into the thead local storage only happens to work due to the write barrier's implementation -- clean up the C code generator. Full of cruft. Misc diff --git a/web/news.txt b/web/news.txt index ac7971f20..5cc3a6ed6 100644 --- a/web/news.txt +++ b/web/news.txt @@ -20,7 +20,9 @@ News ``addHandler``, ``getHandlers``, ``setLogFilter`` and ``getLogFilter`` should be used instead. - ``nim idetools`` has been replaced by a separate tool `nimsuggest`_. - + - *arrow like* operators are not right associative anymore. + - Typeless parameters are now only allowed in templates and macros. The old + way turned out to be too error-prone. Language Additions ------------------ @@ -30,6 +32,15 @@ News - Automatic dereferencing is now done for the first argument of a routine call if overloading resolution produces no match otherwise. This feature has to be enabled with the `experimental`_ pragma. + - Objects that do not use inheritance nor ``case`` can be put into ``const`` + sections. This means that finally this is possible and produces rather + nice code: + + .. code-block:: nim + import tables + + const + foo = {"ah": "finally", "this": "is", "possible.": "nice!"}.toTable() 2014-12-29 Version 0.10.2 released |