Merge branch 'devel' into gcbugfix

This commit is contained in:
Araq 2015-02-10 16:58:50 +01:00
commit 373a79b28a
127 changed files with 1341 additions and 612 deletions

View file

@ -459,7 +459,7 @@ type
tfNeedsInit, # type constains a "not nil" constraint somewhere or some tfNeedsInit, # type constains a "not nil" constraint somewhere or some
# other type so that it requires inititalization # 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 tfHasMeta, # type contains "wildcard" sub-types such as generic params
# or other type classes # or other type classes
tfHasGCedMem, # type contains GC'ed memory tfHasGCedMem, # type contains GC'ed memory
@ -522,7 +522,7 @@ const
skError* = skUnknown skError* = skUnknown
# type flags that are essential for type equality: # type flags that are essential for type equality:
eqTypeFlags* = {tfIterator, tfShared, tfNotNil} eqTypeFlags* = {tfIterator, tfShared, tfNotNil, tfVarIsPtr}
type type
TMagic* = enum # symbols that require compiler magic: TMagic* = enum # symbols that require compiler magic:
@ -1348,7 +1348,7 @@ proc isGCedMem*(t: PType): bool {.inline.} =
proc propagateToOwner*(owner, elem: PType) = proc propagateToOwner*(owner, elem: PType) =
const HaveTheirOwnEmpty = {tySequence, tySet} 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 tfNotNil in elem.flags:
if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvokation}: if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvokation}:
owner.flags.incl tfNotNil owner.flags.incl tfNotNil
@ -1359,9 +1359,6 @@ proc propagateToOwner*(owner, elem: PType) =
if owner.kind in HaveTheirOwnEmpty: discard if owner.kind in HaveTheirOwnEmpty: discard
else: owner.flags.incl tfNeedsInit else: owner.flags.incl tfNeedsInit
if tfShared in elem.flags:
owner.flags.incl tfHasShared
if elem.isMetaType: if elem.isMetaType:
owner.flags.incl tfHasMeta owner.flags.incl tfHasMeta

View file

@ -130,8 +130,8 @@ proc skipConvAndClosure*(n: PNode): PNode =
proc sameValue*(a, b: PNode): bool = proc sameValue*(a, b: PNode): bool =
result = false result = false
case a.kind case a.kind
of nkCharLit..nkInt64Lit: of nkCharLit..nkUInt64Lit:
if b.kind in {nkCharLit..nkInt64Lit}: result = a.intVal == b.intVal if b.kind in {nkCharLit..nkUInt64Lit}: result = a.intVal == b.intVal
of nkFloatLit..nkFloat64Lit: of nkFloatLit..nkFloat64Lit:
if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal == b.floatVal if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal == b.floatVal
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
@ -145,8 +145,8 @@ proc leValue*(a, b: PNode): bool =
# a <= b? # a <= b?
result = false result = false
case a.kind case a.kind
of nkCharLit..nkInt64Lit: of nkCharLit..nkUInt32Lit:
if b.kind in {nkCharLit..nkInt64Lit}: result = a.intVal <= b.intVal if b.kind in {nkCharLit..nkUInt32Lit}: result = a.intVal <= b.intVal
of nkFloatLit..nkFloat64Lit: of nkFloatLit..nkFloat64Lit:
if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal <= b.floatVal if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal <= b.floatVal
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:

View file

@ -125,7 +125,7 @@ proc genArgStringToCString(p: BProc, n: PNode): PRope {.inline.} =
initLocExpr(p, n.sons[0], a) initLocExpr(p, n.sons[0], a)
result = ropef("$1->data", [a.rdLoc]) 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 var a: TLoc
if n.kind == nkStringToCString: if n.kind == nkStringToCString:
result = genArgStringToCString(p, n) result = genArgStringToCString(p, n)
@ -138,6 +138,14 @@ proc genArg(p: BProc, n: PNode, param: PSym): PRope =
elif p.module.compileToCpp and param.typ.kind == tyVar and elif p.module.compileToCpp and param.typ.kind == tyVar and
n.kind == nkHiddenAddr: n.kind == nkHiddenAddr:
initLocExprSingleUse(p, n.sons[0], a) 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) result = rdLoc(a)
else: else:
initLocExprSingleUse(p, n, a) initLocExprSingleUse(p, n, a)
@ -166,7 +174,7 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
if params != nil: app(params, ~", ") if params != nil: app(params, ~", ")
if i < sonsLen(typ): if i < sonsLen(typ):
assert(typ.n.sons[i].kind == nkSym) 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: else:
app(params, genArgNoParam(p, ri.sons[i])) app(params, genArgNoParam(p, ri.sons[i]))
fixupCall(p, le, ri, d, op.r, params) fixupCall(p, le, ri, d, op.r, params)
@ -192,7 +200,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
assert(sonsLen(typ) == sonsLen(typ.n)) assert(sonsLen(typ) == sonsLen(typ.n))
if i < sonsLen(typ): if i < sonsLen(typ):
assert(typ.n.sons[i].kind == nkSym) 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: else:
app(pl, genArgNoParam(p, ri.sons[i])) app(pl, genArgNoParam(p, ri.sons[i]))
if i < length - 1: app(pl, ~", ") if i < length - 1: app(pl, ~", ")
@ -295,7 +303,7 @@ proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType): PRope =
if x.typ.kind == tyPtr: if x.typ.kind == tyPtr:
result = genArgNoParam(p, x) result = genArgNoParam(p, x)
result.app("->") result.app("->")
elif x.kind in {nkHiddenDeref, nkDerefExpr}: elif x.kind in {nkHiddenDeref, nkDerefExpr} and x[0].typ.kind == tyPtr:
result = genArgNoParam(p, x[0]) result = genArgNoParam(p, x[0])
result.app("->") result.app("->")
else: else:
@ -424,12 +432,12 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
assert(sonsLen(typ) == sonsLen(typ.n)) assert(sonsLen(typ) == sonsLen(typ.n))
if length > 1: 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, ~" ")
app(pl, op.r) app(pl, op.r)
if length > 2: if length > 2:
app(pl, ~": ") 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): for i in countup(3, length-1):
assert(sonsLen(typ) == sonsLen(typ.n)) assert(sonsLen(typ) == sonsLen(typ.n))
if i >= sonsLen(typ): if i >= sonsLen(typ):
@ -439,7 +447,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
app(pl, ~" ") app(pl, ~" ")
app(pl, param.name.s) app(pl, param.name.s)
app(pl, ~": ") 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 typ.sons[0] != nil:
if isInvalidReturnType(typ.sons[0]): if isInvalidReturnType(typ.sons[0]):
if sonsLen(ri) > 1: app(pl, ~" ") if sonsLen(ri) > 1: app(pl, ~" ")

View file

@ -83,7 +83,9 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): PRope =
else: else:
result = toRope("NIM_NIL") result = toRope("NIM_NIL")
of nkStrLit..nkTripleStrLit: 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) var id = nodeTableTestOrSet(p.module.dataCache, n, gBackendId)
if id == gBackendId: if id == gBackendId:
# string literal not found in the cache: # string literal not found in the cache:
@ -664,7 +666,8 @@ proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
proc isCppRef(p: BProc; typ: PType): bool {.inline.} = proc isCppRef(p: BProc; typ: PType): bool {.inline.} =
result = p.module.compileToCpp and result = p.module.compileToCpp and
skipTypes(typ, abstractInst).kind == tyVar skipTypes(typ, abstractInst).kind == tyVar and
tfVarIsPtr notin skipTypes(typ, abstractInst).flags
proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) = proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
let mt = mapType(e.sons[0].typ) let mt = mapType(e.sons[0].typ)
@ -677,12 +680,14 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) =
else: else:
var a: TLoc var a: TLoc
initLocExprSingleUse(p, e.sons[0], a) initLocExprSingleUse(p, e.sons[0], a)
case skipTypes(a.t, abstractInst).kind let typ = skipTypes(a.t, abstractInst)
case typ.kind
of tyRef: of tyRef:
d.s = OnHeap d.s = OnHeap
of tyVar: of tyVar:
d.s = OnUnknown d.s = OnUnknown
if p.module.compileToCpp: if tfVarIsPtr notin typ.flags and p.module.compileToCpp and
e.kind == nkHiddenDeref:
putIntoDest(p, d, e.typ, rdLoc(a)) putIntoDest(p, d, e.typ, rdLoc(a))
return return
of tyPtr: of tyPtr:
@ -923,6 +928,7 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
L: TLabel L: TLabel
tmp: TLoc tmp: TLoc
getTemp(p, e.typ, tmp) # force it into a temp! getTemp(p, e.typ, tmp) # force it into a temp!
inc p.splitDecls
expr(p, e.sons[1], tmp) expr(p, e.sons[1], tmp)
L = getLabel(p) L = getLabel(p)
if m == mOr: if m == mOr:
@ -935,6 +941,7 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
d = tmp d = tmp
else: else:
genAssignment(p, d, tmp, {}) # no need for deep copying genAssignment(p, d, tmp, {}) # no need for deep copying
dec p.splitDecls
proc genEcho(p: BProc, n: PNode) = proc genEcho(p: BProc, n: PNode) =
# this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)`` # this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)``
@ -945,7 +952,7 @@ proc genEcho(p: BProc, n: PNode) =
var a: TLoc var a: TLoc
for i in countup(0, n.len-1): for i in countup(0, n.len-1):
initLocExpr(p, n.sons[i], a) 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", linefmt(p, cpsStmts, "printf($1$2);$n",
makeCString(repeatStr(n.len, "%s") & tnl), args) makeCString(repeatStr(n.len, "%s") & tnl), args)
@ -2168,7 +2175,7 @@ proc genConstExpr(p: BProc, n: PNode): PRope =
var cs: TBitSet var cs: TBitSet
toBitSet(n, cs) toBitSet(n, cs)
result = genRawSetData(cs, int(getSize(n.typ))) result = genRawSetData(cs, int(getSize(n.typ)))
of nkBracket, nkPar, nkClosure: of nkBracket, nkPar, nkClosure, nkObjConstr:
var t = skipTypes(n.typ, abstractInst) var t = skipTypes(n.typ, abstractInst)
if t.kind == tySequence: if t.kind == tySequence:
result = genConstSeq(p, n, t) result = genConstSeq(p, n, t)

View file

@ -203,7 +203,7 @@ proc genSingleVar(p: BProc, a: PNode) =
registerGcRoot(p, v) registerGcRoot(p, v)
else: else:
let imm = isAssignedImmediately(a.sons[2]) let imm = isAssignedImmediately(a.sons[2])
if imm and p.module.compileToCpp: 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 # C++ really doesn't like things like 'Foo f; f = x' as that invokes a
# parameterless constructor followed by an assignment operator. So we # parameterless constructor followed by an assignment operator. So we
# generate better code here: # generate better code here:
@ -253,15 +253,6 @@ proc genConstStmt(p: BProc, t: PNode) =
elif c.typ.kind in ConstantDataTypes and lfNoDecl notin c.loc.flags and elif c.typ.kind in ConstantDataTypes and lfNoDecl notin c.loc.flags and
c.ast.len != 0: c.ast.len != 0:
if not emitLazily(c): requestConstImpl(p, c) 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) = proc genIf(p: BProc, n: PNode, d: var TLoc) =
# #
@ -286,17 +277,22 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
let it = n.sons[i] let it = n.sons[i]
if it.len == 2: if it.len == 2:
when newScopeForIf: startBlock(p) when newScopeForIf: startBlock(p)
initLocExpr(p, it.sons[0], a) initLocExprSingleUse(p, it.sons[0], a)
lelse = getLabel(p) lelse = getLabel(p)
inc(p.labels) inc(p.labels)
lineFF(p, cpsStmts, "if (!$1) goto $2;$n", lineF(p, cpsStmts, "if (!$1) goto $2;$n",
"br i1 $1, label %LOC$3, label %$2$nLOC$3: $n", [rdLoc(a), lelse])
[rdLoc(a), lelse, toRope(p.labels)])
when not newScopeForIf: startBlock(p) when not newScopeForIf: startBlock(p)
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) expr(p, it.sons[1], d)
endBlock(p) endBlock(p)
if sonsLen(n) > 1: 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) fixLabel(p, lelse)
elif it.len == 1: elif it.len == 1:
startBlock(p) startBlock(p)
@ -355,7 +351,7 @@ proc genReturnStmt(p: BProc, t: PNode) =
# consume it before we return. # consume it before we return.
var safePoint = p.finallySafePoints[p.finallySafePoints.len-1] var safePoint = p.finallySafePoints[p.finallySafePoints.len-1]
linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", safePoint) 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) = proc genComputedGoto(p: BProc; n: PNode) =
# first pass: Generate array of computed labels: # first pass: Generate array of computed labels:

View file

@ -28,16 +28,6 @@ proc isKeyword(w: PIdent): bool =
proc mangleName(s: PSym): PRope = proc mangleName(s: PSym): PRope =
result = s.loc.r result = s.loc.r
if result == nil: 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")
when oKeepVariableNames: when oKeepVariableNames:
let keepOrigName = s.kind in skLocalVars - {skForVar} and let keepOrigName = s.kind in skLocalVars - {skForVar} and
{sfFromGeneric, sfGlobal, sfShadowed, sfGenSym} * s.flags == {} and {sfFromGeneric, sfGlobal, sfShadowed, sfGenSym} * s.flags == {} and
@ -103,13 +93,11 @@ proc typeName(typ: PType): PRope =
else: ~"TY" else: ~"TY"
proc getTypeName(typ: PType): PRope = proc getTypeName(typ: PType): PRope =
if (typ.sym != nil) and ({sfImportc, sfExportc} * typ.sym.flags != {}) and if typ.sym != nil and {sfImportc, sfExportc} * typ.sym.flags != {}:
(gCmd != cmdCompileToLLVM):
result = typ.sym.loc.r result = typ.sym.loc.r
else: else:
if typ.loc.r == nil: if typ.loc.r == nil:
typ.loc.r = if gCmd != cmdCompileToLLVM: con(typ.typeName, typ.id.toRope) typ.loc.r = con(typ.typeName, typ.id.toRope)
else: con([~"%", typ.typeName, typ.id.toRope])
result = typ.loc.r result = typ.loc.r
if result == nil: internalError("getTypeName: " & $typ.kind) if result == nil: internalError("getTypeName: " & $typ.kind)
@ -200,9 +188,6 @@ const
"N_SYSCALL", # this is probably not correct for all platforms, "N_SYSCALL", # this is probably not correct for all platforms,
# but one can #define it to what one wants # but one can #define it to what one wants
"N_INLINE", "N_NOINLINE", "N_FASTCALL", "N_CLOSURE", "N_NOCONV"] "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 = proc cacheGetType(tab: TIdTable, key: PType): PRope =
# returns nil if we need to declare this type # returns nil if we need to declare this type
@ -284,23 +269,23 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var PRope,
# this fixes the 'sort' bug: # this fixes the 'sort' bug:
if param.typ.kind == tyVar: param.loc.s = OnUnknown if param.typ.kind == tyVar: param.loc.s = OnUnknown
# need to pass hidden parameter: # 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) inc(j)
arr = arr.sons[0] 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] var arr = t.sons[0]
if params != nil: app(params, ", ") if params != nil: app(params, ", ")
app(params, getTypeDescAux(m, arr, check)) app(params, getTypeDescAux(m, arr, check))
if (mapReturnType(t.sons[0]) != ctArray) or (gCmd == cmdCompileToLLVM): if (mapReturnType(t.sons[0]) != ctArray):
app(params, "*") app(params, "*")
appff(params, " Result", " @Result", []) appf(params, " Result", [])
if t.callConv == ccClosure and declareEnvironment: if t.callConv == ccClosure and declareEnvironment:
if params != nil: app(params, ", ") if params != nil: app(params, ", ")
app(params, "void* ClEnv") app(params, "void* ClEnv")
if tfVarargs in t.flags: if tfVarargs in t.flags:
if params != nil: app(params, ", ") if params != nil: app(params, ", ")
app(params, "...") app(params, "...")
if params == nil and gCmd != cmdCompileToLLVM: app(params, "void)") if params == nil: app(params, "void)")
else: app(params, ")") else: app(params, ")")
params = con("(", params) params = con("(", params)
@ -506,7 +491,8 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
# C type generation into an analysis and a code generation phase somehow. # C type generation into an analysis and a code generation phase somehow.
case t.kind case t.kind
of tyRef, tyPtr, tyVar: of tyRef, tyPtr, tyVar:
let star = if t.kind == tyVar and compileToCpp(m): "&" else: "*" var star = if t.kind == tyVar and tfVarIsPtr notin typ.flags and
compileToCpp(m): "&" else: "*"
var et = t.lastSon var et = t.lastSon
var etB = et.skipTypes(abstractInst) var etB = et.skipTypes(abstractInst)
if etB.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}: if etB.kind in {tyArrayConstr, tyArray, tyOpenArray, tyVarargs}:
@ -514,6 +500,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
# ``var set[char]`` in `getParamTypeDesc` # ``var set[char]`` in `getParamTypeDesc`
et = elemType(etB) et = elemType(etB)
etB = et.skipTypes(abstractInst) etB = et.skipTypes(abstractInst)
star[0] = '*'
case etB.kind case etB.kind
of tyObject, tyTuple: of tyObject, tyTuple:
if isImportedCppType(etB) and et.kind == tyGenericInst: if isImportedCppType(etB) and et.kind == tyGenericInst:
@ -529,7 +516,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var IntSet): PRope =
# no restriction! We have a forward declaration for structs # no restriction! We have a forward declaration for structs
let x = getUniqueType(etB) let x = getUniqueType(etB)
let name = getTypeForward(m, x) let name = getTypeForward(m, x)
result = con(name, "**") result = con(name, "*" & star)
idTablePut(m.typeCache, t, result) idTablePut(m.typeCache, t, result)
pushType(m, x) pushType(m, x)
else: else:
@ -677,7 +664,7 @@ proc genProcHeader(m: BModule, prc: PSym): PRope =
rettype, params: PRope rettype, params: PRope
genCLineDir(result, prc.info) genCLineDir(result, prc.info)
# using static is needed for inline procs # 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: if m.isHeaderFile:
result.app "N_LIB_IMPORT " result.app "N_LIB_IMPORT "
else: else:

View file

@ -25,15 +25,6 @@ when options.hasTinyCBackend:
var var
generatedHeader: BModule 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) = proc addForwardedProc(m: BModule, prc: PSym) =
m.forwardedProcs.add(prc) m.forwardedProcs.add(prc)
inc(gForwardedProcsCounter) inc(gForwardedProcsCounter)
@ -137,78 +128,7 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope =
if i - 1 >= start: if i - 1 >= start:
app(result, substr(frmt, start, i - 1)) app(result, substr(frmt, start, i - 1))
const compileTimeRopeFmt = false template rfmt(m: BModule, fmt: string, args: varargs[PRope]): expr =
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) ropecg(m, fmt, args)
proc appcg(m: BModule, c: var PRope, frmt: TFormatStr, proc appcg(m: BModule, c: var PRope, frmt: TFormatStr,
@ -242,12 +162,7 @@ proc lineCg(p: BProc, s: TCProcSection, frmt: TFormatStr,
args: varargs[PRope]) = args: varargs[PRope]) =
app(p.s(s), indentLine(p, ropecg(p.module, frmt, args))) app(p.s(s), indentLine(p, ropecg(p.module, frmt, args)))
when compileTimeRopeFmt: proc linefmt(p: BProc, s: TCProcSection, frmt: TFormatStr,
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]) = args: varargs[PRope]) =
app(p.s(s), indentLine(p, ropecg(p.module, frmt, args))) app(p.s(s), indentLine(p, ropecg(p.module, frmt, args)))
@ -255,11 +170,6 @@ proc appLineCg(p: BProc, r: var PRope, frmt: TFormatStr,
args: varargs[PRope]) = args: varargs[PRope]) =
app(r, indentLine(p, ropecg(p.module, frmt, args))) 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 = proc safeLineNm(info: TLineInfo): int =
result = toLinenumber(info) result = toLinenumber(info)
if result < 0: result = 0 # negative numbers are not allowed in #line if result < 0: result = 0 # negative numbers are not allowed in #line
@ -267,7 +177,7 @@ proc safeLineNm(info: TLineInfo): int =
proc genCLineDir(r: var PRope, filename: string, line: int) = proc genCLineDir(r: var PRope, filename: string, line: int) =
assert line >= 0 assert line >= 0
if optLineDir in gOptions: if optLineDir in gOptions:
appff(r, "$N#line $2 $1$N", "; line $2 \"$1\"$n", appf(r, "$N#line $2 $1$N",
[toRope(makeSingleLineCString(filename)), toRope(line)]) [toRope(makeSingleLineCString(filename)), toRope(line)])
proc genCLineDir(r: var PRope, info: TLineInfo) = proc genCLineDir(r: var PRope, info: TLineInfo) =
@ -444,29 +354,6 @@ proc deinitGCFrame(p: BProc): PRope =
result = ropecg(p.module, result = ropecg(p.module,
"if (((NU)&GCFRAME) < 4096) #nimGCFrame(&GCFRAME);$n") "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) = proc allocParam(p: BProc, s: PSym) =
assert(s.kind == skParam) assert(s.kind == skParam)
if lfParamCopy notin s.loc.flags: if lfParamCopy notin s.loc.flags:
@ -507,7 +394,7 @@ proc localVarDecl(p: BProc; s: PSym): PRope =
result = ropef(s.cgDeclFrmt, result, s.loc.r) result = ropef(s.cgDeclFrmt, result, s.loc.r)
proc assignLocalVar(p: BProc, s: PSym) = proc assignLocalVar(p: BProc, s: PSym) =
#assert(s.loc.k == locNone) // not yet assigned #assert(s.loc.k == locNone) # not yet assigned
# this need not be fullfilled for inline procs; they are regenerated # this need not be fullfilled for inline procs; they are regenerated
# for each module that uses them! # for each module that uses them!
let decl = localVarDecl(p, s).con(";" & tnl) let decl = localVarDecl(p, s).con(";" & tnl)
@ -553,13 +440,11 @@ proc assignGlobalVar(p: BProc, s: PSym) =
{optStackTrace, optEndb}: {optStackTrace, optEndb}:
appcg(p.module, p.module.s[cfsDebugInit], appcg(p.module, p.module.s[cfsDebugInit],
"#dbgRegisterGlobal($1, &$2, $3);$n", "#dbgRegisterGlobal($1, &$2, $3);$n",
[cstringLit(p, p.module.s[cfsDebugInit], [makeCString(normalize(s.owner.name.s & '.' & s.name.s)),
normalize(s.owner.name.s & '.' & s.name.s)),
s.loc.r, genTypeInfo(p.module, s.typ)]) s.loc.r, genTypeInfo(p.module, s.typ)])
proc assignParam(p: BProc, s: PSym) = proc assignParam(p: BProc, s: PSym) =
assert(s.loc.r != nil) assert(s.loc.r != nil)
if sfAddrTaken in s.flags and gCmd == cmdCompileToLLVM: allocParam(p, s)
localDebugInfo(p, s) localDebugInfo(p, s)
proc fillProcLoc(sym: PSym) = proc fillProcLoc(sym: PSym) =
@ -653,7 +538,6 @@ proc symInDynamicLib(m: BModule, sym: PSym) =
let isCall = isGetProcAddr(lib) let isCall = isGetProcAddr(lib)
var extname = sym.loc.r var extname = sym.loc.r
if not isCall: loadDynamicLib(m, lib) if not isCall: loadDynamicLib(m, lib)
if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
var tmp = mangleDynLibProc(sym) var tmp = mangleDynLibProc(sym)
sym.loc.r = tmp # from now on we only need the internal name sym.loc.r = tmp # from now on we only need the internal name
sym.typ.sym = nil # generate a new name sym.typ.sym = nil # generate a new name
@ -669,7 +553,7 @@ proc symInDynamicLib(m: BModule, sym: PSym) =
params.app(", ") params.app(", ")
let load = ropef("\t$1 = ($2) ($3$4));$n", let load = ropef("\t$1 = ($2) ($3$4));$n",
[tmp, getTypeDesc(m, sym.typ), [tmp, getTypeDesc(m, sym.typ),
params, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname))]) params, makeCString(ropeToStr(extname))])
var last = lastSon(n) var last = lastSon(n)
if last.kind == nkHiddenStdConv: last = last.sons[1] if last.kind == nkHiddenStdConv: last = last.sons[1]
internalAssert(last.kind == nkStrLit) internalAssert(last.kind == nkStrLit)
@ -684,10 +568,8 @@ proc symInDynamicLib(m: BModule, sym: PSym) =
appcg(m, m.s[cfsDynLibInit], appcg(m, m.s[cfsDynLibInit],
"\t$1 = ($2) #nimGetProcAddr($3, $4);$n", "\t$1 = ($2) #nimGetProcAddr($3, $4);$n",
[tmp, getTypeDesc(m, sym.typ), [tmp, getTypeDesc(m, sym.typ),
lib.name, cstringLit(m, m.s[cfsDynLibInit], ropeToStr(extname))]) lib.name, makeCString(ropeToStr(extname))])
appff(m.s[cfsVars], "$2 $1;$n", appf(m.s[cfsVars], "$2 $1;$n", [sym.loc.r, getTypeDesc(m, sym.loc.t)])
"$1 = linkonce global $2 zeroinitializer$n",
[sym.loc.r, getTypeDesc(m, sym.loc.t)])
proc varInDynamicLib(m: BModule, sym: PSym) = proc varInDynamicLib(m: BModule, sym: PSym) =
var lib = sym.annex var lib = sym.annex
@ -700,7 +582,7 @@ proc varInDynamicLib(m: BModule, sym: PSym) =
appcg(m, m.s[cfsDynLibInit], appcg(m, m.s[cfsDynLibInit],
"$1 = ($2*) #nimGetProcAddr($3, $4);$n", "$1 = ($2*) #nimGetProcAddr($3, $4);$n",
[tmp, getTypeDesc(m, sym.typ), [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", appf(m.s[cfsVars], "$2* $1;$n",
[sym.loc.r, getTypeDesc(m, sym.loc.t)]) [sym.loc.r, getTypeDesc(m, sym.loc.t)])
@ -802,16 +684,17 @@ proc genProcAux(m: BModule, prc: PSym) =
app(generatedProc, initGCFrame(p)) app(generatedProc, initGCFrame(p))
if optStackTrace in prc.options: if optStackTrace in prc.options:
app(generatedProc, p.s(cpsLocals)) 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)) app(generatedProc, initFrame(p, procname, prc.info.quotedFilename))
else: else:
app(generatedProc, p.s(cpsLocals)) app(generatedProc, p.s(cpsLocals))
if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM): if optProfiler in prc.options:
# invoke at proc entry for recursion: # invoke at proc entry for recursion:
appcg(p, cpsInit, "\t#nimProfile();$n", []) appcg(p, cpsInit, "\t#nimProfile();$n", [])
if p.beforeRetNeeded: app(generatedProc, "{")
app(generatedProc, p.s(cpsInit)) app(generatedProc, p.s(cpsInit))
app(generatedProc, p.s(cpsStmts)) app(generatedProc, p.s(cpsStmts))
if p.beforeRetNeeded: app(generatedProc, ~"\tBeforeRet: ;$n") if p.beforeRetNeeded: app(generatedProc, ~"\t}BeforeRet: ;$n")
app(generatedProc, deinitGCFrame(p)) app(generatedProc, deinitGCFrame(p))
if optStackTrace in prc.options: app(generatedProc, deinitFrame(p)) if optStackTrace in prc.options: app(generatedProc, deinitFrame(p))
app(generatedProc, returnStmt) app(generatedProc, returnStmt)
@ -831,7 +714,6 @@ proc genProcPrototype(m: BModule, sym: PSym) =
not containsOrIncl(m.declaredThings, sym.id): not containsOrIncl(m.declaredThings, sym.id):
app(m.s[cfsVars], rfmt(nil, "extern $1 $2;$n", app(m.s[cfsVars], rfmt(nil, "extern $1 $2;$n",
getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym))) getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)))
if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
elif not containsOrIncl(m.declaredProtos, sym.id): elif not containsOrIncl(m.declaredProtos, sym.id):
var header = genProcHeader(m, sym) var header = genProcHeader(m, sym)
if sym.typ.callConv != ccInline and crossesCppBoundary(m, sym): if sym.typ.callConv != ccInline and crossesCppBoundary(m, sym):
@ -929,21 +811,17 @@ proc addIntTypes(result: var PRope) {.inline.} =
proc getCopyright(cfile: string): PRope = proc getCopyright(cfile: string): PRope =
if optCompileOnly in gGlobalOptions: 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" & "/* (c) 2015 Andreas Rumpf */$N" &
"/* The generated code is subject to the original license. */$N", "/* The generated code is subject to the original license. */$N",
"; Generated by Nim Compiler v$1$N" & [toRope(VersionAsString)])
"; (c) 2012 Andreas Rumpf$N", [toRope(VersionAsString)])
else: else:
result = ropeff("/* Generated by Nim Compiler v$1 */$N" & result = ropef("/* Generated by Nim Compiler v$1 */$N" &
"/* (c) 2015 Andreas Rumpf */$N" & "/* (c) 2015 Andreas Rumpf */$N" &
"/* The generated code is subject to the original license. */$N" & "/* The generated code is subject to the original license. */$N" &
"/* Compiled for: $2, $3, $4 */$N" & "/* Compiled for: $2, $3, $4 */$N" &
"/* Command for C compiler:$n $5 */$N", "/* Command for C compiler:$n $5 */$N",
"; Generated by Nim Compiler v$1$N" & [toRope(VersionAsString),
"; (c) 2015 Andreas Rumpf$N" &
"; Compiled for: $2, $3, $4$N" &
"; Command for LLVM compiler:$N $5$N", [toRope(VersionAsString),
toRope(platform.OS[targetOS].name), toRope(platform.OS[targetOS].name),
toRope(platform.CPU[targetCPU].name), toRope(platform.CPU[targetCPU].name),
toRope(extccomp.CC[extccomp.cCompiler].name), toRope(extccomp.CC[extccomp.cCompiler].name),
@ -1094,13 +972,11 @@ proc registerModuleToMain(m: PSym) =
var var
init = m.getInitName init = m.getInitName
datInit = m.getDatInitName datInit = m.getDatInitName
appff(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", appf(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", [init])
"declare void $1() noinline$N", [init]) appf(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N", [datInit])
appff(mainModProcs, "NIM_EXTERNC N_NOINLINE(void, $1)(void);$N",
"declare void $1() noinline$N", [datInit])
if sfSystemModule notin m.flags: if sfSystemModule notin m.flags:
appff(mainDatInit, "\t$1();$N", "call void ()* $1$n", [datInit]) appf(mainDatInit, "\t$1();$N", [datInit])
let initCall = ropeff("\t$1();$N", "call void ()* $1$n", [init]) let initCall = ropef("\t$1();$N", [init])
if sfMainModule in m.flags: if sfMainModule in m.flags:
app(mainModInit, initCall) app(mainModInit, initCall)
else: else:
@ -1108,8 +984,7 @@ proc registerModuleToMain(m: PSym) =
proc genInitCode(m: BModule) = proc genInitCode(m: BModule) =
var initname = getInitName(m.module) var initname = getInitName(m.module)
var prc = ropeff("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N", var prc = ropef("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N", [initname])
"define void $1() noinline {$n", [initname])
if m.typeNodes > 0: if m.typeNodes > 0:
appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n", appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n",
[m.typeNodesName, toRope(m.typeNodes)]) [m.typeNodesName, toRope(m.typeNodes)])
@ -1130,7 +1005,7 @@ proc genInitCode(m: BModule) =
# declare it nevertheless: # declare it nevertheless:
m.frameDeclared = true m.frameDeclared = true
if not m.preventStackTrace: 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)) app(prc, initFrame(m.initProc, procname, m.module.info.quotedFilename))
else: else:
app(prc, ~"\tTFrame F; F.len = 0;$N") app(prc, ~"\tTFrame F; F.len = 0;$N")
@ -1151,8 +1026,8 @@ proc genInitCode(m: BModule) =
app(prc, deinitGCFrame(m.initProc)) app(prc, deinitGCFrame(m.initProc))
appf(prc, "}$N$N") appf(prc, "}$N$N")
prc.appff("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N", prc.appf("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N",
"define void $1() noinline {$n", [getDatInitName(m.module)]) [getDatInitName(m.module)])
for i in cfsTypeInit1..cfsDynLibInit: for i in cfsTypeInit1..cfsDynLibInit:
app(prc, genSectionStart(i)) app(prc, genSectionStart(i))

View file

@ -82,6 +82,9 @@ type
maxFrameLen*: int # max length of frame descriptor maxFrameLen*: int # max length of frame descriptor
module*: BModule # used to prevent excessive parameter passing module*: BModule # used to prevent excessive parameter passing
withinLoop*: int # > 0 if we are within a loop 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 gcFrameId*: Natural # for the GC stack marking
gcFrameType*: PRope # the struct {} we put the GC markers into gcFrameType*: PRope # the struct {} we put the GC markers into

View file

@ -52,7 +52,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo)
const const
HelpMessage = "Nim Compiler Version $1 (" & CompileDate & ") [$2: $3]\n" & 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 const
Usage = slurp"doc/basicopt.txt".replace("//", "") Usage = slurp"doc/basicopt.txt".replace("//", "")

View file

@ -428,13 +428,17 @@ proc addFileToLink*(filename: string) =
prependStr(toLink, filename) prependStr(toLink, filename)
# BUGFIX: was ``appendStr`` # BUGFIX: was ``appendStr``
proc execExternalProgram*(cmd: string, prettyCmd = "") = proc execWithEcho(cmd: string, prettyCmd = ""): int =
if optListCmd in gGlobalOptions or gVerbosity > 0: if optListCmd in gGlobalOptions or gVerbosity > 0:
if prettyCmd != "": if prettyCmd != "":
msgWriteln(prettyCmd) msgWriteln(prettyCmd)
else: else:
msgWriteln(cmd) 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) = proc generateScript(projectFile: string, script: PRope) =
let (dir, name, ext) = splitFile(projectFile) let (dir, name, ext) = splitFile(projectFile)
@ -622,7 +626,9 @@ proc callCCompiler*(projectfile: string) =
if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors() if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors()
var res = 0 var res = 0
if gNumberOfProcessors <= 1: if gNumberOfProcessors <= 1:
for i in countup(0, high(cmds)): res = max(execCmd(cmds[i]), res) for i in countup(0, high(cmds)):
res = execWithEcho(cmds[i])
if res != 0: rawMessage(errExecutionOfProgramFailed, [])
elif optListCmd in gGlobalOptions or gVerbosity > 1: elif optListCmd in gGlobalOptions or gVerbosity > 1:
res = execProcesses(cmds, {poEchoCmd, poUseShell, poParentStreams}, res = execProcesses(cmds, {poEchoCmd, poUseShell, poParentStreams},
gNumberOfProcessors) gNumberOfProcessors)

View file

@ -30,47 +30,32 @@ type
PLLStream* = ref TLLStream PLLStream* = ref TLLStream
proc llStreamOpen*(data: string): PLLStream 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 =
new(result) new(result)
result.s = data result.s = data
result.kind = llsString result.kind = llsString
proc llStreamOpen(f: var File): PLLStream = proc llStreamOpen*(f: var File): PLLStream =
new(result) new(result)
result.f = f result.f = f
result.kind = llsFile result.kind = llsFile
proc llStreamOpen(filename: string, mode: FileMode): PLLStream = proc llStreamOpen*(filename: string, mode: FileMode): PLLStream =
new(result) new(result)
result.kind = llsFile result.kind = llsFile
if not open(result.f, filename, mode): result = nil if not open(result.f, filename, mode): result = nil
proc llStreamOpen(): PLLStream = proc llStreamOpen*(): PLLStream =
new(result) new(result)
result.kind = llsNone result.kind = llsNone
proc llStreamOpenStdIn(): PLLStream = proc llStreamOpenStdIn*(): PLLStream =
new(result) new(result)
result.kind = llsStdIn result.kind = llsStdIn
result.s = "" result.s = ""
result.lineOffset = -1 result.lineOffset = -1
proc llStreamClose(s: PLLStream) = proc llStreamClose*(s: PLLStream) =
case s.kind case s.kind
of llsNone, llsString, llsStdIn: of llsNone, llsString, llsStdIn:
discard discard
@ -130,7 +115,7 @@ proc llReadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int =
copyMem(buf, addr(s.s[s.rd]), result) copyMem(buf, addr(s.s[s.rd]), result)
inc(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 case s.kind
of llsNone: of llsNone:
result = 0 result = 0
@ -144,7 +129,7 @@ proc llStreamRead(s: PLLStream, buf: pointer, bufLen: int): int =
of llsStdIn: of llsStdIn:
result = llReadFromStdin(s, buf, bufLen) result = llReadFromStdin(s, buf, bufLen)
proc llStreamReadLine(s: PLLStream, line: var string): bool = proc llStreamReadLine*(s: PLLStream, line: var string): bool =
setLen(line, 0) setLen(line, 0)
case s.kind case s.kind
of llsNone: of llsNone:
@ -168,7 +153,7 @@ proc llStreamReadLine(s: PLLStream, line: var string): bool =
of llsStdIn: of llsStdIn:
result = readLine(stdin, line) result = readLine(stdin, line)
proc llStreamWrite(s: PLLStream, data: string) = proc llStreamWrite*(s: PLLStream, data: string) =
case s.kind case s.kind
of llsNone, llsStdIn: of llsNone, llsStdIn:
discard discard
@ -178,11 +163,11 @@ proc llStreamWrite(s: PLLStream, data: string) =
of llsFile: of llsFile:
write(s.f, data) write(s.f, data)
proc llStreamWriteln(s: PLLStream, data: string) = proc llStreamWriteln*(s: PLLStream, data: string) =
llStreamWrite(s, data) llStreamWrite(s, data)
llStreamWrite(s, "\n") llStreamWrite(s, "\n")
proc llStreamWrite(s: PLLStream, data: char) = proc llStreamWrite*(s: PLLStream, data: char) =
var c: char var c: char
case s.kind case s.kind
of llsNone, llsStdIn: of llsNone, llsStdIn:
@ -194,7 +179,7 @@ proc llStreamWrite(s: PLLStream, data: char) =
c = data c = data
discard writeBuffer(s.f, addr(c), sizeof(c)) 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 case s.kind
of llsNone, llsStdIn: of llsNone, llsStdIn:
discard discard
@ -206,7 +191,7 @@ proc llStreamWrite(s: PLLStream, buf: pointer, buflen: int) =
of llsFile: of llsFile:
discard writeBuffer(s.f, buf, buflen) discard writeBuffer(s.f, buf, buflen)
proc llStreamReadAll(s: PLLStream): string = proc llStreamReadAll*(s: PLLStream): string =
const const
bufSize = 2048 bufSize = 2048
case s.kind case s.kind

View file

@ -251,7 +251,6 @@ proc mainCommand* =
commandCompileToC() commandCompileToC()
of "cpp", "compiletocpp": of "cpp", "compiletocpp":
gCmd = cmdCompileToCpp gCmd = cmdCompileToCpp
if cCompiler == ccGcc: setCC("gcc")
defineSymbol("cpp") defineSymbol("cpp")
commandCompileToC() commandCompileToC()
of "objc", "compiletooc": of "objc", "compiletooc":

View file

@ -113,7 +113,7 @@ type
warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel, warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel,
warnUnknownSubstitutionX, warnLanguageXNotSupported, warnUnknownSubstitutionX, warnLanguageXNotSupported,
warnFieldXNotSupported, warnCommentXIgnored, warnFieldXNotSupported, warnCommentXIgnored,
warnNilStatement, warnAnalysisLoophole, warnNilStatement, warnTypelessParam,
warnDifferentHeaps, warnWriteToForeignHeap, warnUnsafeCode, warnDifferentHeaps, warnWriteToForeignHeap, warnUnsafeCode,
warnEachIdentIsTuple, warnShadowIdent, warnEachIdentIsTuple, warnShadowIdent,
warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2, warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2,
@ -311,7 +311,7 @@ const
errXOnlyAtModuleScope: "\'$1\' is only allowed at top level", errXOnlyAtModuleScope: "\'$1\' is only allowed at top level",
errXNeedsParamObjectType: "'$1' needs a parameter that has an object type", errXNeedsParamObjectType: "'$1' needs a parameter that has an object type",
errTemplateInstantiationTooNested: "template/macro instantiation too nested", errTemplateInstantiationTooNested: "template/macro instantiation too nested",
errInstantiationFrom: "instantiation from here", errInstantiationFrom: "template/generic instantiation from here",
errInvalidIndexValueForTuple: "invalid index value for tuple subscript", errInvalidIndexValueForTuple: "invalid index value for tuple subscript",
errCommandExpectsFilename: "command expects a filename argument", errCommandExpectsFilename: "command expects a filename argument",
errMainModuleMustBeSpecified: "please, specify a main module in the project configuration file", errMainModuleMustBeSpecified: "please, specify a main module in the project configuration file",
@ -376,7 +376,7 @@ const
warnFieldXNotSupported: "field \'$1\' not supported [FieldXNotSupported]", warnFieldXNotSupported: "field \'$1\' not supported [FieldXNotSupported]",
warnCommentXIgnored: "comment \'$1\' ignored [CommentXIgnored]", warnCommentXIgnored: "comment \'$1\' ignored [CommentXIgnored]",
warnNilStatement: "'nil' statement is deprecated; use an empty 'discard' statement instead [NilStmt]", 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]", warnDifferentHeaps: "possible inconsistency of thread local heaps [DifferentHeaps]",
warnWriteToForeignHeap: "write to foreign heap [WriteToForeignHeap]", warnWriteToForeignHeap: "write to foreign heap [WriteToForeignHeap]",
warnUnsafeCode: "unsafe code: '$1' [UnsafeCode]", warnUnsafeCode: "unsafe code: '$1' [UnsafeCode]",
@ -418,7 +418,7 @@ const
"RedefinitionOfLabel", "UnknownSubstitutionX", "RedefinitionOfLabel", "UnknownSubstitutionX",
"LanguageXNotSupported", "FieldXNotSupported", "LanguageXNotSupported", "FieldXNotSupported",
"CommentXIgnored", "NilStmt", "CommentXIgnored", "NilStmt",
"AnalysisLoophole", "DifferentHeaps", "WriteToForeignHeap", "TypelessParam", "DifferentHeaps", "WriteToForeignHeap",
"UnsafeCode", "EachIdentIsTuple", "ShadowIdent", "UnsafeCode", "EachIdentIsTuple", "ShadowIdent",
"ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit", "ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit",
"GcMem", "Destructor", "LockLevel", "User"] "GcMem", "Destructor", "LockLevel", "User"]
@ -460,7 +460,7 @@ type
TLineInfo*{.final.} = object # This is designed to be as small as possible, TLineInfo*{.final.} = object # This is designed to be as small as possible,
# because it is used # 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. # two int16 and an int32.
# On 64 bit and on 32 bit systems this is # On 64 bit and on 32 bit systems this is
# only 8 bytes. # only 8 bytes.
@ -522,7 +522,7 @@ proc newFileInfo(fullPath, projPath: string): TFileInfo =
if optEmbedOrigSrc in gGlobalOptions or true: if optEmbedOrigSrc in gGlobalOptions or true:
result.lines = @[] result.lines = @[]
proc fileInfoIdx*(filename: string): int32 = proc fileInfoIdx*(filename: string; isKnownFile: var bool): int32 =
var var
canon: string canon: string
pseudoPath = false pseudoPath = false
@ -539,11 +539,16 @@ proc fileInfoIdx*(filename: string): int32 =
if filenameToIndexTbl.hasKey(canon): if filenameToIndexTbl.hasKey(canon):
result = filenameToIndexTbl[canon] result = filenameToIndexTbl[canon]
else: else:
isKnownFile = false
result = fileInfos.len.int32 result = fileInfos.len.int32
fileInfos.add(newFileInfo(canon, if pseudoPath: filename fileInfos.add(newFileInfo(canon, if pseudoPath: filename
else: canon.shortenDir)) else: canon.shortenDir))
filenameToIndexTbl[canon] = result filenameToIndexTbl[canon] = result
proc fileInfoIdx*(filename: string): int32 =
var dummy: bool
result = fileInfoIdx(filename, dummy)
proc newLineInfo*(fileInfoIdx: int32, line, col: int): TLineInfo = proc newLineInfo*(fileInfoIdx: int32, line, col: int): TLineInfo =
result.fileIndex = fileInfoIdx result.fileIndex = fileInfoIdx
result.line = int16(line) result.line = int16(line)

View file

@ -11,10 +11,10 @@
import import
llstream, nversion, commands, os, strutils, msgs, platform, condsyms, lexer, llstream, nversion, commands, os, strutils, msgs, platform, condsyms, lexer,
options, idents, wordrecg options, idents, wordrecg, strtabs
# ---------------- configuration file parser ----------------------------- # ---------------- 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) = proc ppGetTok(L: var TLexer, tok: var TToken) =
# simple filter # simple filter
@ -82,17 +82,17 @@ proc doElif(L: var TLexer, tok: var TToken) =
proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest) = proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest) =
var nestedIfs = 0 var nestedIfs = 0
while true: while true:
if (tok.ident != nil) and (tok.ident.s == "@"): if tok.ident != nil and tok.ident.s == "@":
ppGetTok(L, tok) ppGetTok(L, tok)
case whichKeyword(tok.ident) case whichKeyword(tok.ident)
of wIf: of wIf:
inc(nestedIfs) inc(nestedIfs)
of wElse: of wElse:
if (dest == jdElseEndif) and (nestedIfs == 0): if dest == jdElseEndif and nestedIfs == 0:
doElse(L, tok) doElse(L, tok)
break break
of wElif: of wElif:
if (dest == jdElseEndif) and (nestedIfs == 0): if dest == jdElseEndif and nestedIfs == 0:
doElif(L, tok) doElif(L, tok)
break break
of wEnd: of wEnd:
@ -121,7 +121,8 @@ proc parseDirective(L: var TLexer, tok: var TToken) =
of wEnd: doEnd(L, tok) of wEnd: doEnd(L, tok)
of wWrite: of wWrite:
ppGetTok(L, tok) ppGetTok(L, tok)
msgs.msgWriteln(tokToStr(tok)) msgs.msgWriteln(strtabs.`%`(tokToStr(tok), options.gConfigVars,
{useEnvironment, useKey}))
ppGetTok(L, tok) ppGetTok(L, tok)
else: else:
case tok.ident.s.normalize case tok.ident.s.normalize
@ -157,7 +158,7 @@ proc checkSymbol(L: TLexer, tok: TToken) =
proc parseAssignment(L: var TLexer, tok: var TToken) = proc parseAssignment(L: var TLexer, tok: var TToken) =
if tok.ident.id == getIdent("-").id or tok.ident.id == getIdent("--").id: if tok.ident.id == getIdent("-").id or tok.ident.id == getIdent("--").id:
confTok(L, tok) # skip unnecessary prefix 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) checkSymbol(L, tok)
var s = tokToStr(tok) var s = tokToStr(tok)
confTok(L, tok) # skip symbol confTok(L, tok) # skip symbol
@ -178,9 +179,10 @@ proc parseAssignment(L: var TLexer, tok: var TToken) =
if tok.tokType == tkBracketRi: confTok(L, tok) if tok.tokType == tkBracketRi: confTok(L, tok)
else: lexMessage(L, errTokenExpected, "']'") else: lexMessage(L, errTokenExpected, "']'")
add(val, ']') 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, ':') if len(val) > 0: add(val, ':')
confTok(L, tok) # skip ':' or '=' confTok(L, tok) # skip ':' or '=' or '%'
checkSymbol(L, tok) checkSymbol(L, tok)
add(val, tokToStr(tok)) add(val, tokToStr(tok))
confTok(L, tok) # skip symbol confTok(L, tok) # skip symbol
@ -189,6 +191,10 @@ proc parseAssignment(L: var TLexer, tok: var TToken) =
checkSymbol(L, tok) checkSymbol(L, tok)
add(val, tokToStr(tok)) add(val, tokToStr(tok))
confTok(L, tok) confTok(L, tok)
if percent:
processSwitch(s, strtabs.`%`(val, options.gConfigVars,
{useEnvironment, useEmpty}), passPP, info)
else:
processSwitch(s, val, passPP, info) processSwitch(s, val, passPP, info)
proc readConfigFile(filename: string) = proc readConfigFile(filename: string) =
@ -246,6 +252,11 @@ proc loadConfigs*(cfg: string) =
if gProjectName.len != 0: if gProjectName.len != 0:
# new project wide config file: # new project wide config file:
let projectConfig = changeFileExt(gProjectFull, "nim.cfg") var projectConfig = changeFileExt(gProjectFull, "nimcfg")
if fileExists(projectConfig): readConfigFile(projectConfig) if not fileExists(projectConfig):
else: readConfigFile(changeFileExt(gProjectFull, "nimrod.cfg")) projectConfig = changeFileExt(gProjectFull, "nim.cfg")
if not fileExists(projectConfig):
projectConfig = changeFileExt(gProjectFull, "nimrod.cfg")
if fileExists(projectConfig):
rawMessage(warnDeprecated, projectConfig)
readConfigFile(projectConfig)

View file

@ -87,8 +87,9 @@ proc action(cmd: string) =
i += skipWhile(cmd, seps, i) i += skipWhile(cmd, seps, i)
i += parseInt(cmd, col, i) i += parseInt(cmd, col, i)
var isKnownFile = true
if orig.len == 0: err() if orig.len == 0: err()
let dirtyIdx = orig.fileInfoIdx let dirtyIdx = orig.fileInfoIdx(isKnownFile)
if dirtyfile.len != 0: msgs.setDirtyFile(dirtyIdx, dirtyfile) if dirtyfile.len != 0: msgs.setDirtyFile(dirtyIdx, dirtyfile)
else: msgs.setDirtyFile(dirtyIdx, nil) else: msgs.setDirtyFile(dirtyIdx, nil)
@ -99,6 +100,9 @@ proc action(cmd: string) =
gTrackPos = newLineInfo(dirtyIdx, line, col) gTrackPos = newLineInfo(dirtyIdx, line, col)
#echo dirtyfile, gDirtyBufferIdx, " project ", gProjectMainIdx #echo dirtyfile, gDirtyBufferIdx, " project ", gProjectMainIdx
gErrorCounter = 0 gErrorCounter = 0
if not isKnownFile:
compileProject(dirtyIdx)
else:
compileProject() compileProject()
proc serve() = proc serve() =

View file

@ -198,8 +198,8 @@ proc isSigilLike(tok: TToken): bool {.inline.} =
proc isRightAssociative(tok: TToken): bool {.inline.} = proc isRightAssociative(tok: TToken): bool {.inline.} =
## Determines whether the token is right assocative. ## Determines whether the token is right assocative.
result = tok.tokType == tkOpr and (tok.ident.s[0] == '^' or result = tok.tokType == tkOpr and tok.ident.s[0] == '^'
(let L = tok.ident.s.len; L > 1 and tok.ident.s[L-1] == '>')) # or (let L = tok.ident.s.len; L > 1 and tok.ident.s[L-1] == '>'))
proc getPrecedence(tok: TToken, strongSpaces: bool): int = proc getPrecedence(tok: TToken, strongSpaces: bool): int =
## Calculates the precedence of the given token. ## Calculates the precedence of the given token.

View file

@ -138,7 +138,7 @@ const
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}), props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
(name: "VxWorks", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/", (name: "VxWorks", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ";", dirSep: "\\", objExt: ".o", newLine: "\x0A", pathSep: ";", dirSep: "\\",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".", scriptExt: ".sh", curDir: ".", exeExt: ".vxe", extSep: ".",
props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}), props: {ospNeedsPIC, ospPosix, ospLacksThreadVars}),
(name: "JS", parDir: "..", (name: "JS", parDir: "..",
dllFrmt: "lib$1.so", altDirSep: "/", dllFrmt: "lib$1.so", altDirSep: "/",

View file

@ -130,9 +130,11 @@ proc commonType*(x, y: PType): PType =
elif a.kind == tyTuple and b.kind == tyTuple and a.len == b.len: elif a.kind == tyTuple and b.kind == tyTuple and a.len == b.len:
var nt: PType var nt: PType
for i in 0.. <a.len: for i in 0.. <a.len:
if isEmptyContainer(a.sons[i]) and not isEmptyContainer(b.sons[i]): let aEmpty = isEmptyContainer(a.sons[i])
let bEmpty = isEmptyContainer(b.sons[i])
if aEmpty != bEmpty:
if nt.isNil: nt = copyType(a, a.owner, false) if nt.isNil: nt = copyType(a, a.owner, false)
nt.sons[i] = b.sons[i] nt.sons[i] = if aEmpty: b.sons[i] else: a.sons[i]
if not nt.isNil: result = nt if not nt.isNil: result = nt
#elif b.sons[idx].kind == tyEmpty: return x #elif b.sons[idx].kind == tyEmpty: return x
elif a.kind == tyRange and b.kind == tyRange: elif a.kind == tyRange and b.kind == tyRange:

View file

@ -221,6 +221,7 @@ proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
proc makeTypeFromExpr*(c: PContext, n: PNode): PType = proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
result = newTypeS(tyFromExpr, c) result = newTypeS(tyFromExpr, c)
assert n != nil
result.n = n result.n = n
proc newTypeWithSons*(c: PContext, kind: TTypeKind, proc newTypeWithSons*(c: PContext, kind: TTypeKind,

View file

@ -103,13 +103,9 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
result = newSymNode(s, n.info) result = newSymNode(s, n.info)
of skMacro: result = semMacroExpr(c, n, n, s, flags) of skMacro: result = semMacroExpr(c, n, n, s, flags)
of skTemplate: result = semTemplateExpr(c, n, s, flags) of skTemplate: result = semTemplateExpr(c, n, s, flags)
of skVar, skLet, skResult, skParam, skForVar: of skParam:
markUsed(n.info, s) markUsed(n.info, s)
styleCheckUse(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: if s.typ.kind == tyStatic and s.typ.n != nil:
# XXX see the hack in sigmatch.nim ... # XXX see the hack in sigmatch.nim ...
return s.typ.n return s.typ.n
@ -126,6 +122,13 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
internalAssert u != nil and u.kind == skParam and u.owner == s.owner internalAssert u != nil and u.kind == skParam and u.owner == s.owner
return newSymNode(u, n.info) return newSymNode(u, n.info)
result = newSymNode(s, 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)
result = newSymNode(s, n.info)
# We cannot check for access to outer vars for example because it's still # We cannot check for access to outer vars for example because it's still
# not sure the symbol really ends up being used: # not sure the symbol really ends up being used:
# var len = 0 # but won't be called # var len = 0 # but won't be called
@ -445,20 +448,25 @@ proc changeType(n: PNode, newType: PType, check: bool) =
let tup = newType.skipTypes({tyGenericInst}) let tup = newType.skipTypes({tyGenericInst})
if tup.kind != tyTuple: if tup.kind != tyTuple:
internalError(n.info, "changeType: no tuple type for constructor") internalError(n.info, "changeType: no tuple type for constructor")
elif newType.n == nil: discard
elif sonsLen(n) > 0 and n.sons[0].kind == nkExprColonExpr: elif sonsLen(n) > 0 and n.sons[0].kind == nkExprColonExpr:
# named tuple?
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var m = n.sons[i].sons[0] var m = n.sons[i].sons[0]
if m.kind != nkSym: if m.kind != nkSym:
internalError(m.info, "changeType(): invalid tuple constr") internalError(m.info, "changeType(): invalid tuple constr")
return return
if tup.n != nil:
var f = getSymFromList(newType.n, m.sym.name) var f = getSymFromList(newType.n, m.sym.name)
if f == nil: if f == nil:
internalError(m.info, "changeType(): invalid identifier") internalError(m.info, "changeType(): invalid identifier")
return return
changeType(n.sons[i].sons[1], f.typ, check) changeType(n.sons[i].sons[1], f.typ, check)
else:
changeType(n.sons[i].sons[1], tup.sons[i], check)
else: else:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
changeType(n.sons[i], tup.sons[i], check)
when false:
var m = n.sons[i] var m = n.sons[i]
var a = newNodeIT(nkExprColonExpr, m.info, newType.sons[i]) var a = newNodeIT(nkExprColonExpr, m.info, newType.sons[i])
addSon(a, newSymNode(newType.n.sons[i].sym)) addSon(a, newSymNode(newType.n.sons[i].sym))
@ -579,7 +587,8 @@ proc isAssignable(c: PContext, n: PNode): TAssignableResult =
result = parampatterns.isAssignable(c.p.owner, n) result = parampatterns.isAssignable(c.p.owner, n)
proc newHiddenAddrTaken(c: PContext, n: PNode): PNode = proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
if n.kind == nkHiddenDeref: if n.kind == nkHiddenDeref and not (gCmd == cmdCompileToCpp or
sfCompileToCpp in c.module.flags):
checkSonsLen(n, 1) checkSonsLen(n, 1)
result = n.sons[0] result = n.sons[0]
else: else:
@ -1209,6 +1218,7 @@ proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
if x.typ.kind == tyVar and x.kind == nkSym and x.sym.kind == skResult: if x.typ.kind == tyVar and x.kind == nkSym and x.sym.kind == skResult:
n.sons[0] = x # 'result[]' --> 'result' n.sons[0] = x # 'result[]' --> 'result'
n.sons[1] = takeImplicitAddr(c, ri) n.sons[1] = takeImplicitAddr(c, ri)
x.typ.flags.incl tfVarIsPtr
template resultTypeIsInferrable(typ: PType): expr = template resultTypeIsInferrable(typ: PType): expr =
typ.isMetaType and typ.kind != tyTypeDesc typ.isMetaType and typ.kind != tyTypeDesc

View file

@ -77,11 +77,16 @@ proc removeDefaultParamValues(n: PNode) =
proc freshGenSyms(n: PNode, owner: PSym, symMap: var TIdTable) = proc freshGenSyms(n: PNode, owner: PSym, symMap: var TIdTable) =
# we need to create a fresh set of gensym'ed symbols: # we need to create a fresh set of gensym'ed symbols:
if n.kind == nkSym and sfGenSym in n.sym.flags: 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: if x == nil:
x = copySym(n.sym, false) if s.kind == skParam:
x = owner.typ.n[s.position+1].sym
internalAssert x.kind == skParam
else:
x = copySym(s, false)
x.owner = owner x.owner = owner
idTablePut(symMap, n.sym, x) idTablePut(symMap, s, x)
n.sym = x n.sym = x
else: else:
for i in 0 .. <safeLen(n): freshGenSyms(n.sons[i], owner, symMap) for i in 0 .. <safeLen(n): freshGenSyms(n.sons[i], owner, symMap)

View file

@ -359,6 +359,10 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
var def: PNode var def: PNode
if a.sons[length-1].kind != nkEmpty: if a.sons[length-1].kind != nkEmpty:
def = semExprWithType(c, a.sons[length-1], {efAllowDestructor}) def = semExprWithType(c, a.sons[length-1], {efAllowDestructor})
if def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro:
# prevent the all too common 'var x = int' bug:
localError(def.info, "'typedesc' metatype is not valid here; typed '=' instead of ':'?")
def.typ = errorType(c)
if typ != nil: if typ != nil:
if typ.isMetaType: if typ.isMetaType:
def = inferWithMetatype(c, typ, def) def = inferWithMetatype(c, typ, def)
@ -825,9 +829,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): if gp.len == 0 or (gp.len == 1 and tfRetType in gp[0].typ.flags):
pushProcCon(c, s) pushProcCon(c, s)
addResult(c, s.typ.sons[0], n.info, skProc) addResult(c, s.typ.sons[0], n.info, skProc)
addResultNode(c, n)
let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos])) let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
n.sons[bodyPos] = transformBody(c.module, semBody, s) n.sons[bodyPos] = transformBody(c.module, semBody, s)
addResultNode(c, n)
popProcCon(c) popProcCon(c)
elif efOperand notin flags: elif efOperand notin flags:
localError(n.info, errGenericLambdaNotAllowed) localError(n.info, errGenericLambdaNotAllowed)
@ -860,9 +864,9 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
addParams(c, n.typ.n, skProc) addParams(c, n.typ.n, skProc)
pushProcCon(c, s) pushProcCon(c, s)
addResult(c, n.typ.sons[0], n.info, skProc) addResult(c, n.typ.sons[0], n.info, skProc)
addResultNode(c, n)
let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos])) let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
n.sons[bodyPos] = transformBody(c.module, semBody, n.sons[namePos].sym) n.sons[bodyPos] = transformBody(c.module, semBody, n.sons[namePos].sym)
addResultNode(c, n)
popProcCon(c) popProcCon(c)
popOwner() popOwner()
closeScope(c) closeScope(c)

View file

@ -781,9 +781,10 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
result.rawAddSon(paramType) result.rawAddSon(paramType)
for i in 0 .. paramType.sonsLen - 2: for i in 0 .. paramType.sonsLen - 2:
let dummyType = if paramType.sons[i].kind == tyStatic: tyUnknown if paramType.sons[i].kind == tyStatic:
else: tyAnything result.rawAddSon makeTypeFromExpr(c, ast.emptyNode) # aka 'tyUnkown'
result.rawAddSon newTypeS(dummyType, c) else:
result.rawAddSon newTypeS(tyAnything, c)
if paramType.lastSon.kind == tyUserTypeClass: if paramType.lastSon.kind == tyUserTypeClass:
result.kind = tyUserTypeClassInst result.kind = tyUserTypeClassInst
@ -911,6 +912,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
if not hasType and not hasDefault: if not hasType and not hasDefault:
if isType: localError(a.info, "':' expected") if isType: localError(a.info, "':' expected")
let tdef = if kind in {skTemplate, skMacro}: tyExpr else: tyAnything let tdef = if kind in {skTemplate, skMacro}: tyExpr else: tyAnything
if tdef == tyAnything:
message(a.info, warnTypelessParam, renderTree(n))
typ = newTypeS(tdef, c) typ = newTypeS(tdef, c)
if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue

View file

@ -1056,7 +1056,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
of tyFromExpr: of tyFromExpr:
# fix the expression, so it contains the already instantiated types # fix the expression, so it contains the already instantiated types
if f.n == nil: return isGeneric if f.n == nil or f.n.kind == nkEmpty: return isGeneric
let reevaluated = tryResolvingStaticExpr(c, f.n) let reevaluated = tryResolvingStaticExpr(c, f.n)
case reevaluated.typ.kind case reevaluated.typ.kind
of tyTypeDesc: of tyTypeDesc:

View file

@ -321,6 +321,7 @@ proc transformYield(c: PTransf, n: PNode): PTransNode =
proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode = proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
result = transformSons(c, n) result = transformSons(c, n)
if gCmd == cmdCompileToCpp or sfCompileToCpp in c.module.flags: return
var n = result.PNode var n = result.PNode
case n.sons[0].kind case n.sons[0].kind
of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64: of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:

View file

@ -29,6 +29,7 @@ proc hashTree(n: PNode): THash =
if (n.floatVal >= - 1000000.0) and (n.floatVal <= 1000000.0): if (n.floatVal >= - 1000000.0) and (n.floatVal <= 1000000.0):
result = result !& toInt(n.floatVal) result = result !& toInt(n.floatVal)
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
if not n.strVal.isNil:
result = result !& hash(n.strVal) result = result !& hash(n.strVal)
else: else:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):

View file

@ -1038,7 +1038,9 @@ proc typeAllowedNode(marker: var IntSet, n: PNode, kind: TSymKind,
discard discard
else: else:
for i in countup(0, sonsLen(n) - 1): 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 if result != nil: break
proc matchType*(a: PType, pattern: openArray[tuple[k:TTypeKind, i:int]], 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) result = typeAllowedAux(marker, t.sons[i], kind, flags)
if result != nil: break if result != nil: break
of tyObject, tyTuple: 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} let flags = flags+{taField}
for i in countup(0, sonsLen(t) - 1): for i in countup(0, sonsLen(t) - 1):
result = typeAllowedAux(marker, t.sons[i], kind, flags) result = typeAllowedAux(marker, t.sons[i], kind, flags)

View file

@ -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 # immediate macros can bypass any type and arity checking so we check the
# arity here too: # arity here too:
if sym.typ.len > n.safeLen and sym.typ.len > 1: 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) setupGlobalCtx(module)
var c = globalCtx var c = globalCtx

View file

@ -604,7 +604,8 @@ proc genNarrowU(c: PCtx; n: PNode; dest: TDest) =
let t = skipTypes(n.typ, abstractVar-{tyTypeDesc}) let t = skipTypes(n.typ, abstractVar-{tyTypeDesc})
# uint is uint64 in the VM, we we only need to mask the result for # uint is uint64 in the VM, we we only need to mask the result for
# other unsigned types: # 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)) c.gABC(n, opcNarrowU, dest, TRegister(t.size*8))
proc genBinaryABCnarrow(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) = proc genBinaryABCnarrow(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =

View file

@ -5,7 +5,8 @@
# You may set environment variables with # You may set environment variables with
# @putenv "key" "val" # @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 cc = gcc
@ -21,6 +22,7 @@ mips.linux.gcc.linkerexe = "mips-openwrt-linux-gcc"
@end @end
path="$lib/core" path="$lib/core"
path="$lib/pure" path="$lib/pure"
path="$lib/pure/collections" path="$lib/pure/collections"
path="$lib/pure/concurrency" path="$lib/pure/concurrency"
@ -110,6 +112,20 @@ hint[LineTooLong]=off
gcc.cpp.options.always = "-w -fpermissive" gcc.cpp.options.always = "-w -fpermissive"
@end @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.speed = "-O3 -fno-strict-aliasing"
gcc.options.size = "-Os" gcc.options.size = "-Os"
gcc.options.debug = "-g3 -O0" gcc.options.debug = "-g3 -O0"

View file

@ -66,7 +66,6 @@ Advanced options:
--threadanalysis:on|off turn thread analysis on|off --threadanalysis:on|off turn thread analysis on|off
--tlsEmulation:on|off turn thread local storage emulation on|off --tlsEmulation:on|off turn thread local storage emulation on|off
--taintMode:on|off turn taint mode 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 --implicitStatic:on|off turn implicit compile time evaluation on|off
--patterns:on|off turn pattern matching on|off --patterns:on|off turn pattern matching on|off
--skipCfg do not read the general configuration file --skipCfg do not read the general configuration file

View file

@ -14,7 +14,6 @@ Options:
-p, --path:PATH add path to search paths -p, --path:PATH add path to search paths
-d, --define:SYMBOL define a conditional symbol -d, --define:SYMBOL define a conditional symbol
-u, --undef:SYMBOL undefine a conditional symbol -u, --undef:SYMBOL undefine a conditional symbol
--symbol:SYMBOL declare a conditional symbol
-f, --forceBuild force rebuilding of all modules -f, --forceBuild force rebuilding of all modules
--stackTrace:on|off turn stack tracing on|off --stackTrace:on|off turn stack tracing on|off
--lineTrace:on|off turn line tracing on|off --lineTrace:on|off turn line tracing on|off

View file

@ -12,10 +12,8 @@ Binary operators have 11 different levels of precedence.
Associativity Associativity
------------- -------------
Binary operators whose first character is ``^`` or its last character Binary operators whose first character is ``^`` are right-associative, all
is ``>`` are right-associative, all other binary operators are left-associative. other binary operators are left-associative.
Exception: The single "greater than" ``>`` operator is left-associative too.
Operators ending in ``>`` but longer than a single character are Operators ending in ``>`` but longer than a single character are
called `arrow like`:idx:. called `arrow like`:idx:.

View file

@ -190,6 +190,6 @@ Real world example
The installers for the Nim compiler itself are generated by niminst. Have a The installers for the Nim compiler itself are generated by niminst. Have a
look at its configuration file: look at its configuration file:
.. include:: compiler/nim.ini .. include:: compiler/installer.ini
:literal: :literal:

View file

@ -97,13 +97,13 @@ const
compileNimInst = "-d:useLibzipSrc tools/niminst/niminst" compileNimInst = "-d:useLibzipSrc tools/niminst/niminst"
proc csource(args: string) = proc csource(args: string) =
exec("$4 cc $1 -r $3 --var:version=$2 --var:mingw=none csource compiler/nim.ini $1" % exec("$4 cc $1 -r $3 --var:version=$2 --var:mingw=none csource compiler/installer.ini $1" %
[args, VersionAsString, compileNimInst, findNim()]) [args, VersionAsString, compileNimInst, findNim()])
proc zip(args: string) = proc zip(args: string) =
exec("$3 cc -r $2 --var:version=$1 --var:mingw=none scripts compiler/nim.ini" % exec("$3 cc -r $2 --var:version=$1 --var:mingw=none scripts compiler/installer.ini" %
[VersionAsString, compileNimInst, findNim()]) [VersionAsString, compileNimInst, findNim()])
exec("$# --var:version=$# --var:mingw=none zip compiler/nim.ini" % exec("$# --var:version=$# --var:mingw=none zip compiler/installer.ini" %
["tools/niminst/niminst".exe, VersionAsString]) ["tools/niminst/niminst".exe, VersionAsString])
proc buildTool(toolname, args: string) = proc buildTool(toolname, args: string) =
@ -121,20 +121,20 @@ proc nsis(args: string) =
" nsis compiler/nim") % [VersionAsString, $(sizeof(pointer)*8)]) " nsis compiler/nim") % [VersionAsString, $(sizeof(pointer)*8)])
proc install(args: string) = proc install(args: string) =
exec("$# cc -r $# --var:version=$# --var:mingw=none scripts compiler/nim.ini" % exec("$# cc -r $# --var:version=$# --var:mingw=none scripts compiler/installer.ini" %
[findNim(), compileNimInst, VersionAsString]) [findNim(), compileNimInst, VersionAsString])
exec("sh ./install.sh $#" % args) exec("sh ./install.sh $#" % args)
proc web(args: string) = proc web(args: string) =
exec("$# cc -r tools/nimweb.nim $# web/nim --putenv:nimversion=$#" % exec("$# cc -r tools/nimweb.nim $# web/website.ini --putenv:nimversion=$#" %
[findNim(), args, VersionAsString]) [findNim(), args, VersionAsString])
proc website(args: string) = proc website(args: string) =
exec("$# cc -r tools/nimweb.nim $# --website web/nim --putenv:nimversion=$#" % exec("$# cc -r tools/nimweb.nim $# --website web/website.ini --putenv:nimversion=$#" %
[findNim(), args, VersionAsString]) [findNim(), args, VersionAsString])
proc pdf(args="") = proc pdf(args="") =
exec("$# cc -r tools/nimweb.nim $# --pdf web/nim --putenv:nimversion=$#" % exec("$# cc -r tools/nimweb.nim $# --pdf web/website.ini --putenv:nimversion=$#" %
[findNim(), args, VersionAsString]) [findNim(), args, VersionAsString])
# -------------- boot --------------------------------------------------------- # -------------- boot ---------------------------------------------------------

View file

@ -1,7 +1,7 @@
# #
# #
# Nim's Runtime Library # Nim's Runtime Library
# (c) Copyright 2012 Andreas Rumpf # (c) Copyright 2015 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -13,6 +13,8 @@
## is used. This suffices because Windows' console already provides the ## is used. This suffices because Windows' console already provides the
## wanted functionality. ## wanted functionality.
{.deadCodeElim: on.}
when defined(Windows): when defined(Windows):
proc readLineFromStdin*(prompt: string): TaintedString {. proc readLineFromStdin*(prompt: string): TaintedString {.
tags: [ReadIOEffect, WriteIOEffect].} = tags: [ReadIOEffect, WriteIOEffect].} =
@ -31,8 +33,26 @@ when defined(Windows):
stdout.write(prompt) stdout.write(prompt)
result = readLine(stdin, line) 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: else:
import readline, history import readline, history, termios, unsigned
proc readLineFromStdin*(prompt: string): TaintedString {. proc readLineFromStdin*(prompt: string): TaintedString {.
tags: [ReadIOEffect, WriteIOEffect].} = tags: [ReadIOEffect, WriteIOEffect].} =
@ -60,3 +80,19 @@ else:
discard readline.bind_key('\t'.ord, doNothing) 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)

View file

@ -379,7 +379,7 @@ static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); }
# define GC_GUARD # define GC_GUARD
#endif #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: On disagreement, your C compiler will say something like:
"error: 'assert_numbits' declared as an array with a negative size" */ "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]; 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 #else
# define NIM_EXTERNC # define NIM_EXTERNC
#endif #endif
/* ---------------- platform specific includes ----------------------- */
/* VxWorks related includes */
#if defined(__VXWORKS__)
# include <sys/types.h>
# include <types/vxWind.h>
# include <tool/gnu/toolMacros.h>
#endif

264
lib/posix/termios.nim Normal file
View file

@ -0,0 +1,264 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
{.deadCodeElim: on.}
import posix
type
Speed* = cuint
Tcflag* = cuint
const
NCCS* = 32
type
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
lflag*: Tcflag # local mode flags
line*: cuchar # line discipline
cc*: array[NCCS, cuchar] # control characters
ispeed*: Speed # input speed
ospeed*: Speed # output speed
# cc characters
const
VINTR* = 0
VQUIT* = 1
VERASE* = 2
VKILL* = 3
VEOF* = 4
VTIME* = 5
VMIN* = 6
VSWTC* = 7
VSTART* = 8
VSTOP* = 9
VSUSP* = 10
VEOL* = 11
VREPRINT* = 12
VDISCARD* = 13
VWERASE* = 14
VLNEXT* = 15
VEOL2* = 16
# iflag bits
const
IGNBRK* = 1
BRKINT* = 2
IGNPAR* = 4
PARMRK* = 10
INPCK* = 20
ISTRIP* = 40
INLCR* = 100
IGNCR* = 200
ICRNL* = 400
IUCLC* = 1000
IXON* = 2000
IXANY* = 4000
IXOFF* = 10000
IMAXBEL* = 20000
IUTF8* = 40000
# oflag bits
const
OPOST* = 1
OLCUC* = 2
ONLCR* = 4
OCRNL* = 10
ONOCR* = 20
ONLRET* = 40
OFILL* = 100
OFDEL* = 200
NLDLY* = 400
NL0* = 0
NL1* = 400
CRDLY* = 3000
CR0* = 0
CR1* = 1000
CR2* = 2000
CR3* = 3000
TABDLY* = 14000
TAB0* = 0
TAB1* = 4000
TAB2* = 10000
TAB3* = 14000
BSDLY* = 20000
BS0* = 0
BS1* = 20000
FFDLY* = 0o000000100000
FF0* = 0
FF1* = 0o000000100000
VTDLY* = 40000
VT0* = 0
VT1* = 40000
XTABS* = 14000
# cflag bit meaning
const
CBAUD* = 10017
B0* = 0
B50* = 1
B75* = 2
B110* = 3
B134* = 4
B150* = 5
B200* = 6
B300* = 7
B600* = 10
B1200* = 11
B1800* = 12
B2400* = 13
B4800* = 14
B9600* = 15
B19200* = 16
B38400* = 17
EXTA* = B19200
EXTB* = B38400
CSIZE* = 60
CS5* = 0
CS6* = 20
CS7* = 40
CS8* = 60
CSTOPB* = 100
CREAD* = 200
PARENB* = 400
PARODD* = 1000
HUPCL* = 2000
CLOCAL* = 4000
CBAUDEX* = 10000
B57600* = 10001
B115200* = 10002
B230400* = 10003
B460800* = 10004
B500000* = 10005
B576000* = 10006
B921600* = 10007
B1000000* = 10010
B1152000* = 10011
B1500000* = 10012
B2000000* = 10013
B2500000* = 10014
B3000000* = 10015
B3500000* = 10016
B4000000* = 10017
MAX_BAUD* = B4000000
CIBAUD* = 2003600000
CMSPAR* = 0o010000000000
CRTSCTS* = 0o020000000000
# lflag bits
const
ISIG* = 1
ICANON* = 2
XCASE* = 4
ECHO* = 10
ECHOE* = 20
ECHOK* = 40
ECHONL* = 100
NOFLSH* = 200
TOSTOP* = 400
ECHOCTL* = 1000
ECHOPRT* = 2000
ECHOKE* = 4000
FLUSHO* = 10000
PENDIN* = 40000
IEXTEN* = 0o000000100000
EXTPROC* = 0o000000200000
# tcflow() and TCXONC use these
const
TCOOFF* = 0
TCOON* = 1
TCIOFF* = 2
TCION* = 3
# tcflush() and TCFLSH use these
const
TCIFLUSH* = 0
TCOFLUSH* = 1
TCIOFLUSH* = 2
# tcsetattr uses these
const
TCSANOW* = 0
TCSADRAIN* = 1
TCSAFLUSH* = 2
# 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
# Return the output baud rate stored in *TERMIOS_P.
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",
header: "<termios.h>".}
# Set the output baud rate stored in *TERMIOS_P to SPEED.
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 {.
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 {.
importc: "cfsetspeed", header: "<termios.h>".}
# Put the state of FD into *TERMIOS_P.
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 {.
importc: "tcsetattr", header: "<termios.h>".}
# Set *TERMIOS_P to indicate raw mode.
proc cfMakeRaw*(termios: ptr Termios) {.importc: "cfmakeraw",
header: "<termios.h>".}
# Send zero bits on FD.
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>".}
# 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",
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",
header: "<termios.h>".}
# Get process group ID for session leader for controlling terminal FD.
proc tcGetSid*(fd: cint): TPid {.importc: "tcgetsid", header: "<termios.h>".}

View file

@ -220,3 +220,62 @@ proc product*[T](x: openArray[seq[T]]): seq[seq[T]] =
result.add(res) result.add(res)
index = 0 index = 0
indexes[index] -=1 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

View file

@ -1064,6 +1064,17 @@ proc accept*(socket: TAsyncFD,
# -- Await Macro # -- Await Macro
proc skipUntilStmtList(node: PNimrodNode): PNimrodNode {.compileTime.} =
# Skips a nest of StmtList's.
result = node
if node[0].kind == nnkStmtList:
result = skipUntilStmtList(node[0])
proc skipStmtList(node: PNimrodNode): PNimrodNode {.compileTime.} =
result = node
if node[0].kind == nnkStmtList:
result = node[0]
template createCb(retFutureSym, iteratorNameSym, template createCb(retFutureSym, iteratorNameSym,
name: expr): stmt {.immediate.} = name: expr): stmt {.immediate.} =
var nameIterVar = iteratorNameSym var nameIterVar = iteratorNameSym
@ -1211,26 +1222,53 @@ proc processBody(node, retFutureSym: PNimrodNode,
of nnkTryStmt: of nnkTryStmt:
# try: await x; except: ... # try: await x; except: ...
result = newNimNode(nnkStmtList, node) result = newNimNode(nnkStmtList, node)
template wrapInTry(n, tryBody: PNimrodNode) =
var temp = n
n[0] = tryBody
tryBody = temp
# Transform ``except`` body.
# TODO: Could we perform some ``await`` transformation here to get it
# working in ``except``?
tryBody[1] = processBody(n[1], retFutureSym, subTypeIsVoid, nil)
proc processForTry(n: PNimrodNode, i: var int, proc processForTry(n: PNimrodNode, i: var int,
res: PNimrodNode): bool {.compileTime.} = res: PNimrodNode): bool {.compileTime.} =
## Transforms the body of the tryStmt. Does not transform the
## body in ``except``.
## Returns true if the tryStmt node was transformed into an ifStmt.
result = false result = false
while i < n[0].len: var skipped = n.skipStmtList()
var processed = processBody(n[0][i], retFutureSym, subTypeIsVoid, n) while i < skipped.len:
if processed.kind != n[0][i].kind or processed.len != n[0][i].len: var processed = processBody(skipped[i], retFutureSym,
subTypeIsVoid, n)
# Check if we transformed the node into an exception check.
# This suggests skipped[i] contains ``await``.
if processed.kind != skipped[i].kind or processed.len != skipped[i].len:
processed = processed.skipUntilStmtList()
expectKind(processed, nnkStmtList) expectKind(processed, nnkStmtList)
expectKind(processed[2][1], nnkElse) expectKind(processed[2][1], nnkElse)
i.inc i.inc
discard processForTry(n, i, processed[2][1][0])
if not processForTry(n, i, processed[2][1][0]):
# We need to wrap the nnkElse nodes back into a tryStmt.
# As they are executed if an exception does not happen
# inside the awaited future.
# The following code will wrap the nodes inside the
# original tryStmt.
wrapInTry(n, processed[2][1][0])
res.add processed res.add processed
result = true result = true
else: else:
res.add n[0][i] res.add skipped[i]
i.inc i.inc
var i = 0 var i = 0
if not processForTry(node, i, result): if not processForTry(node, i, result):
var temp = node # If the tryStmt hasn't been transformed we can just put the body
temp[0] = result # back into it.
result = temp wrapInTry(node, result)
return return
else: discard else: discard
@ -1329,8 +1367,8 @@ macro async*(prc: stmt): stmt {.immediate.} =
result[6] = outerProcBody result[6] = outerProcBody
#echo(treeRepr(result)) #echo(treeRepr(result))
#if prc[0].getName == "catch": if prc[0].getName == "test3":
# echo(toStrLit(result)) echo(toStrLit(result))
proc recvLine*(socket: TAsyncFD): Future[string] {.async.} = proc recvLine*(socket: TAsyncFD): Future[string] {.async.} =
## Reads a line of data from ``socket``. Returned future will complete once ## Reads a line of data from ``socket``. Returned future will complete once

View file

@ -30,9 +30,28 @@
## ##
## 1.3000000000000000e+00 ## 1.3000000000000000e+00
## true ## 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 import
hashes, strutils, lexbase, streams, unicode hashes, strutils, lexbase, streams, unicode, macros
type type
JsonEventKind* = enum ## enumeration of all events that may occur when parsing 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) newSeq(result.elems, elements.len)
for i, p in pairs(elements): result.elems[i] = p 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 = proc `==`* (a,b: JsonNode): bool =
## Check two nodes for equality ## Check two nodes for equality
if a.isNil: if a.isNil:
@ -864,7 +906,7 @@ proc pretty*(node: JsonNode, indent = 2): string =
proc `$`*(node: JsonNode): string = proc `$`*(node: JsonNode): string =
## Converts `node` to its JSON Representation on one line. ## Converts `node` to its JSON Representation on one line.
result = "" result = ""
toPretty(result, node, 1, false) toPretty(result, node, 0, false)
iterator items*(node: JsonNode): JsonNode = iterator items*(node: JsonNode): JsonNode =
## Iterator for the items of `node`. `node` has to be a JArray. ## Iterator for the items of `node`. `node` has to be a JArray.
@ -1101,6 +1143,37 @@ when isMainModule:
except: except:
assert(false, "EInvalidIndex thrown for valid index") 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 """ discard """
while true: while true:
var json = stdin.readLine() var json = stdin.readLine()

View file

@ -186,7 +186,7 @@ proc newRollingFileLogger*(filename = defaultFilename(),
## a new log file will be started and the old will be renamed. ## a new log file will be started and the old will be renamed.
new(result) new(result)
result.levelThreshold = levelThreshold result.levelThreshold = levelThreshold
result.fmtStr = defaultFmtStr result.fmtStr = fmtStr
result.maxLines = maxLines result.maxLines = maxLines
result.f = open(filename, mode) result.f = open(filename, mode)
result.curLine = 0 result.curLine = 0

View file

@ -1074,6 +1074,10 @@ when defined(windows):
# because we support Windows GUI applications, things get really # because we support Windows GUI applications, things get really
# messy here... # messy here...
when useWinUnicode: when useWinUnicode:
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 {. proc strEnd(cstr: WideCString, c = 0'i32): WideCString {.
importc: "wcschr", header: "<string.h>".} importc: "wcschr", header: "<string.h>".}
else: else:

View file

@ -112,7 +112,7 @@ proc `[]`*(t: StringTableRef, key: string): string {.rtl, extern: "nstGet".} =
proc mget*(t: StringTableRef, key: string): var string {. proc mget*(t: StringTableRef, key: string): var string {.
rtl, extern: "nstTake".} = rtl, extern: "nstTake".} =
## retrieves the location at ``t[key]``. If `key` is not in `t`, the ## 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) var index = rawGet(t, key)
if index >= 0: result = t.data[index].val if index >= 0: result = t.data[index].val
else: raise newException(KeyError, "key does not exist: " & key) 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 = "" else: result = ""
if result.len == 0: if result.len == 0:
if useKey in flags: result = '$' & key if useKey in flags: result = '$' & key
elif not (useEmpty in flags): raiseFormatException(key) elif useEmpty notin flags: raiseFormatException(key)
proc newStringTable*(mode: StringTableMode): StringTableRef {. proc newStringTable*(mode: StringTableMode): StringTableRef {.
rtl, extern: "nst$1".} = rtl, extern: "nst$1".} =

View file

@ -45,6 +45,21 @@ when defined(windows):
var var
oldAttr = getAttributes() oldAttr = getAttributes()
proc winGetch(): cint {.header: "<conio.h>", importc: "_getch".}
else:
import termios, unsigned
proc setRaw(fd: FileHandle, time: cint = TCSAFLUSH) =
var mode: Termios
discard fd.tcgetattr(addr mode)
mode.iflag = mode.iflag and not Tcflag(BRKINT or ICRNL or INPCK or ISTRIP or IXON)
mode.oflag = mode.oflag and not Tcflag(OPOST)
mode.cflag = (mode.cflag and not Tcflag(CSIZE or PARENB)) or CS8
mode.lflag = mode.lflag and not Tcflag(ECHO or ICANON or IEXTEN or ISIG)
mode.cc[VMIN] = 1.cuchar
mode.cc[VTIME] = 0.cuchar
discard fd.tcsetattr(time, addr mode)
proc setCursorPos*(x, y: int) = proc setCursorPos*(x, y: int) =
## sets the terminal's cursor to the (x,y) position. (0,0) is the ## sets the terminal's cursor to the (x,y) position. (0,0) is the
## upper left of the screen. ## upper left of the screen.
@ -349,6 +364,19 @@ macro styledEcho*(m: varargs[expr]): stmt =
result.add(newCall(bindSym"write", bindSym"stdout", newStrLitNode("\n"))) result.add(newCall(bindSym"write", bindSym"stdout", newStrLitNode("\n")))
result.add(newCall(bindSym"resetAttributes")) result.add(newCall(bindSym"resetAttributes"))
proc getch*(): char =
## Read a single character from the terminal, blocking until it is entered.
## The character is not printed to the terminal.
when defined(windows):
result = winGetch().char
else:
let fd = getFileHandle(stdin)
var oldMode: Termios
discard fd.tcgetattr(addr oldMode)
fd.setRaw()
result = stdin.readChar()
discard fd.tcsetattr(TCSADRAIN, addr oldMode)
when isMainModule: when isMainModule:
system.addQuitProc(resetAttributes) system.addQuitProc(resetAttributes)
write(stdout, "never mind") write(stdout, "never mind")

View file

@ -39,6 +39,7 @@ when declared(stdout):
when not defined(ECMAScript): when not defined(ECMAScript):
import terminal import terminal
system.addQuitProc(resetAttributes)
type type
TestStatus* = enum OK, FAILED TestStatus* = enum OK, FAILED
@ -234,5 +235,3 @@ if envOutLvl.len > 0:
if $opt == envOutLvl: if $opt == envOutLvl:
outputLevel = opt outputLevel = opt
break break
system.addQuitProc(resetAttributes)

View file

@ -343,7 +343,7 @@ type
## ##
## Each exception has to inherit from `Exception`. See the full `exception ## Each exception has to inherit from `Exception`. See the full `exception
## hierarchy`_. ## hierarchy`_.
parent: ref Exception ## parent exception (can be used as a stack) parent*: ref Exception ## parent exception (can be used as a stack)
name: cstring ## The exception's name is its Nim identifier. name: cstring ## The exception's name is its Nim identifier.
## This field is filled automatically in the ## This field is filled automatically in the
## ``raise`` statement. ## ``raise`` statement.
@ -3161,7 +3161,7 @@ when hostOS != "standalone":
x[j+i] = item[j] x[j+i] = item[j]
inc(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 ## Special compile-time procedure that checks whether `x` can be compiled
## without any semantic error. ## without any semantic error.
## This can be used to check whether a type supports some operation: ## This can be used to check whether a type supports some operation:

View file

@ -205,9 +205,13 @@ proc genericReset(dest: pointer, mt: PNimType) =
case mt.kind case mt.kind
of tyString, tyRef, tySequence: of tyString, tyRef, tySequence:
unsureAsgnRef(cast[PPointer](dest), nil) unsureAsgnRef(cast[PPointer](dest), nil)
of tyObject, tyTuple: of tyTuple:
# we don't need to reset m_type field for tyObject
genericResetAux(dest, mt.node) genericResetAux(dest, mt.node)
of tyObject:
genericResetAux(dest, mt.node)
# also reset the type field for tyObject, for correct branch switching!
var pint = cast[ptr PNimType](dest)
pint[] = nil
of tyArray, tyArrayConstr: of tyArray, tyArrayConstr:
for i in 0..(mt.size div mt.base.size)-1: for i in 0..(mt.size div mt.base.size)-1:
genericReset(cast[pointer](d +% i*% mt.base.size), mt.base) genericReset(cast[pointer](d +% i*% mt.base.size), mt.base)

View file

@ -84,16 +84,18 @@ elif defined(windows) or defined(dos):
type type
THINSTANCE {.importc: "HINSTANCE".} = object THINSTANCE {.importc: "HINSTANCE".} = object
x: pointer x: pointer
proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
importcpp: "(void*)GetProcAddress(@)", header: "<windows.h>", stdcall.}
else: else:
type type
THINSTANCE {.importc: "HINSTANCE".} = pointer THINSTANCE {.importc: "HINSTANCE".} = pointer
proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
importc: "GetProcAddress", header: "<windows.h>", stdcall.}
proc freeLibrary(lib: THINSTANCE) {. proc freeLibrary(lib: THINSTANCE) {.
importc: "FreeLibrary", header: "<windows.h>", stdcall.} importc: "FreeLibrary", header: "<windows.h>", stdcall.}
proc winLoadLibrary(path: cstring): THINSTANCE {. proc winLoadLibrary(path: cstring): THINSTANCE {.
importc: "LoadLibraryA", header: "<windows.h>", stdcall.} importc: "LoadLibraryA", header: "<windows.h>", stdcall.}
proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
importc: "GetProcAddress", header: "<windows.h>", stdcall.}
proc nimUnloadLibrary(lib: TLibHandle) = proc nimUnloadLibrary(lib: TLibHandle) =
freeLibrary(cast[THINSTANCE](lib)) freeLibrary(cast[THINSTANCE](lib))

View file

@ -184,6 +184,12 @@ when (defined(windows) and not defined(useWinAnsi)) or defined(nimdoc):
include "system/widestrs" include "system/widestrs"
when defined(windows) and not defined(useWinAnsi): 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 {. proc wfopen(filename, mode: WideCString): pointer {.
importc: "_wfopen", nodecl.} importc: "_wfopen", nodecl.}
proc wfreopen(filename, mode: WideCString, stream: File): File {. proc wfreopen(filename, mode: WideCString, stream: File): File {.

View file

@ -66,8 +66,24 @@ Copyright (c) 2006-2014 Andreas Rumpf.
All rights reserved. All rights reserved.
# Build Status # Build Status
| |Linux|Windows|Mac| [**Build Waterfall**][waterfall]
|---|---|---|---|
| x86 | ![](http://178.62.143.63:8010/buildstatusimage?builder=linux-x32-builder) | ![](http://178.62.143.63:8010/buildstatusimage?builder=windows-x32-builder) | ![](http://178.62.143.63:8010/buildstatusimage?builder=mac-x32-builder) | | Linux | Windows | Mac |
| x86_64 | ![](http://178.62.143.63:8010/buildstatusimage?builder=linux-x64-builder) | ![](http://178.62.143.63:8010/buildstatusimage?builder=windows-x64-builder) | ![](http://178.62.143.63:8010/buildstatusimage?builder=mac-x64-builder) | ------ | ----- | ------- | --- |
| arm | ![](http://178.62.143.63:8010/buildstatusimage?builder=linux-arm5-builder) | | x86 | ![linux-x86][linux-x86-img] | ![windows-x86][windows-x86-img] | ![mac-x86][mac-x86-img] |
| x86_64 | ![linux-x86_64][linux-x86_64-img] | ![windows-x86_64][windows-x86_64-img] | ![mac-x86_64][mac-x86_64-img] |
| arm | ![linux-armv5][linux-arm5-img]<br/> ![linux-armv6][linux-arm6-img]<br/> ![linux-armv7][linux-arm7-img] | | |
[linux-x86-img]: http://buildbot.nim-lang.org/buildstatusimage?builder=linux-x32-builder
[linux-x86_64-img]: http://buildbot.nim-lang.org/buildstatusimage?builder=linux-x64-builder
[linux-arm5-img]: http://buildbot.nim-lang.org/buildstatusimage?builder=linux-arm5-builder
[linux-arm6-img]: http://buildbot.nim-lang.org/buildstatusimage?builder=linux-arm6-builder
[linux-arm7-img]: http://buildbot.nim-lang.org/buildstatusimage?builder=linux-arm7-builder
[windows-x86-img]: http://buildbot.nim-lang.org/buildstatusimage?builder=windows-x32-builder
[windows-x86_64-img]: http://buildbot.nim-lang.org/buildstatusimage?builder=windows-x64-builder
[mac-x86-img]: http://buildbot.nim-lang.org/buildstatusimage?builder=mac-x32-builder
[mac-x86_64-img]: http://buildbot.nim-lang.org/buildstatusimage?builder=mac-x64-builder
[waterfall]: http://buildbot.nim-lang.org/waterfall

View file

@ -3,7 +3,7 @@ discard """
WARNING: false first assertion from bar WARNING: false first assertion from bar
ERROR: false second assertion from bar ERROR: false second assertion from bar
-1 -1
tfailedassert.nim:27 false assertion from foo tests/assert/tfailedassert.nim:27 false assertion from foo
''' '''
""" """

View file

@ -20,7 +20,6 @@ proc processClient(fd: int) {.async.} =
if foo == 'g': if foo == 'g':
raise newException(EBase, "foobar") raise newException(EBase, "foobar")
proc serve() {.async.} = proc serve() {.async.} =
while true: while true:

View file

@ -49,3 +49,44 @@ proc catch() {.async.} =
assert false assert false
asyncCheck catch() asyncCheck catch()
proc test(): Future[bool] {.async.} =
result = false
try:
raise newException(OSError, "Foobar")
except:
result = true
return
proc foo(): Future[bool] {.async.} = discard
proc test2(): Future[bool] {.async.} =
result = false
try:
discard await foo()
raise newException(OSError, "Foobar")
except:
result = true
return
proc test3(): Future[int] {.async.} =
result = 0
try:
try:
discard await foo()
raise newException(OSError, "Hello")
except:
result = 1
raise
except:
result = 2
return
var x = test()
assert x.read
x = test2()
assert x.read
var y = test3()
assert y.read == 2

View file

@ -1,6 +1,6 @@
discard """ discard """
line: 18 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 #bug #442

View file

@ -1,5 +1,5 @@
discard """ discard """
errormsg: 'type mismatch: got (mc.typ)' errormsg: "type mismatch: got (mc.typ)"
line: 12 line: 12
""" """

View file

@ -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)
)

View file

@ -0,0 +1,5 @@
discard """
cmd: "nim cpp $target"
"""
import rawsockets

5
tests/cpp/ttypeinfo.nim Normal file
View file

@ -0,0 +1,5 @@
discard """
cmd: "nim cpp $target"
"""
import typeinfo

View file

@ -1,5 +1,4 @@
discard """ discard """
line: 2166
file: "system.nim" file: "system.nim"
errormsg: "can raise an unlisted exception: ref IOError" errormsg: "can raise an unlisted exception: ref IOError"
""" """

View file

@ -38,12 +38,14 @@ proc newPlus(a, b: ref TExpr): ref TPlusExpr =
result.b = b result.b = b
result.op2 = $getOccupiedMem() result.op2 = $getOccupiedMem()
const Limit = when compileOption("gc", "markAndSweep"): 5*1024*1024 else: 500_000
for i in 0..100_000: for i in 0..100_000:
var s: array[0..11, ref TExpr] var s: array[0..11, ref TExpr]
for j in 0..high(s): for j in 0..high(s):
s[j] = newPlus(newPlus(newLit(j), newLit(2)), newLit(4)) s[j] = newPlus(newPlus(newLit(j), newLit(2)), newLit(4))
if eval(s[j]) != j+6: if eval(s[j]) != j+6:
quit "error: wrong result" quit "error: wrong result"
if getOccupiedMem() > 500_000: quit("still a leak!") if getOccupiedMem() > Limit: quit("still a leak!")
echo "no leak: ", getOccupiedMem() echo "no leak: ", getOccupiedMem()

View file

@ -1,6 +1,5 @@
discard """ discard """
output: '''TMatrix[3, 3, system.int] output: '''TMatrix[3, 3, system.int]
3
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]) var m = TMatrix[3,3,int](data: [1,2,3,4,5,6,7,8,9])
echoMatrix m echoMatrix m
echoMat2 m #echoMat2 m

View file

@ -1,9 +1,10 @@
discard """ discard """
output: "2" output: '''2
88'''
""" """
type type
TValue* {.pure, final.} = object of TObject TValue* {.pure, final.} = object of RootObj
a: int a: int
PValue = ref TValue PValue = ref TValue
PPValue = ptr PValue PPValue = ptr PValue
@ -16,3 +17,19 @@ var sp: PPValue = addr x
sp.a = 2 sp.a = 2
if sp.a == 2: echo 2 # with sp[].a the error is gone if sp.a == 2: echo 2 # with sp[].a the error is gone
# Test the new auto-deref a little
{.experimental.}
proc p(x: var int; y: int) = x += y
block:
var x: ref int
new(x)
x.p(44)
var indirect = p
x.indirect(44)
echo x[]

24
tests/iter/tconcat.nim Normal file
View file

@ -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

View file

@ -74,7 +74,7 @@ type
contacts*: PContact contacts*: PContact
stamp*: TTimestamp stamp*: TTimestamp
handler*: PCollisionHandler handler*: PCollisionHandler
swappedColl*: bool32 swappedColl*: Bool32
state*: TArbiterState state*: TArbiterState
PCollisionHandler* = ptr TCollisionHandler PCollisionHandler* = ptr TCollisionHandler
TCollisionHandler*{.pf.} = object TCollisionHandler*{.pf.} = object
@ -108,7 +108,7 @@ type
#/ Collision begin event function callback type. #/ Collision begin event function callback type.
#/ Returning false from a begin callback causes the collision to be ignored until #/ Returning false from a begin callback causes the collision to be ignored until
#/ the the separate callback is called when the objects stop colliding. #/ 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.} cdecl.}
#/ Collision pre-solve event function callback type. #/ Collision pre-solve event function callback type.
#/ Returning false from a pre-step callback causes the collision to be ignored until the next step. #/ 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 PSpatialIndex = ptr TSpatialIndex
TSpatialIndex{.pf.} = object TSpatialIndex{.pf.} = object
klass: PSpatialIndexClass klass: PSpatialIndexClass
bbfunc: TSpatialIndexBBFunc bbfun: TSpatialIndexBBFunc
staticIndex: PSpatialIndex staticIndex: PSpatialIndex
dynamicIndex: PSpatialIndex dynamicIndex: PSpatialIndex
TSpatialIndexDestroyImpl* = proc (index: PSpatialIndex){.cdecl.} TSpatialIndexDestroyImpl* = proc (index: PSpatialIndex){.cdecl.}
TSpatialIndexCountImpl* = proc (index: PSpatialIndex): cint{.cdecl.} TSpatialIndexCountImpl* = proc (index: PSpatialIndex): cint{.cdecl.}
TSpatialIndexEachImpl* = proc (index: PSpatialIndex; TSpatialIndexEachImpl* = proc (index: PSpatialIndex;
func: TSpatialIndexIteratorFunc; data: pointer){. fun: TSpatialIndexIteratorFunc; data: pointer){.
cdecl.} cdecl.}
TSpatialIndexContainsImpl* = proc (index: PSpatialIndex; obj: pointer; TSpatialIndexContainsImpl* = proc (index: PSpatialIndex; obj: pointer;
hashid: THashValue): Bool32 {.cdecl.} hashid: THashValue): Bool32 {.cdecl.}
@ -161,15 +161,15 @@ type
TSpatialIndexReindexObjectImpl* = proc (index: PSpatialIndex; TSpatialIndexReindexObjectImpl* = proc (index: PSpatialIndex;
obj: pointer; hashid: THashValue){.cdecl.} obj: pointer; hashid: THashValue){.cdecl.}
TSpatialIndexReindexQueryImpl* = proc (index: PSpatialIndex; TSpatialIndexReindexQueryImpl* = proc (index: PSpatialIndex;
func: TSpatialIndexQueryFunc; data: pointer){.cdecl.} fun: TSpatialIndexQueryFunc; data: pointer){.cdecl.}
TSpatialIndexPointQueryImpl* = proc (index: PSpatialIndex; point: TVector; TSpatialIndexPointQueryImpl* = proc (index: PSpatialIndex; point: TVector;
func: TSpatialIndexQueryFunc; fun: TSpatialIndexQueryFunc;
data: pointer){.cdecl.} data: pointer){.cdecl.}
TSpatialIndexSegmentQueryImpl* = proc (index: PSpatialIndex; obj: pointer; 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.} data: pointer){.cdecl.}
TSpatialIndexQueryImpl* = proc (index: PSpatialIndex; obj: pointer; TSpatialIndexQueryImpl* = proc (index: PSpatialIndex; obj: pointer;
bb: TBB; func: TSpatialIndexQueryFunc; bb: TBB; fun: TSpatialIndexQueryFunc;
data: pointer){.cdecl.} data: pointer){.cdecl.}
PSpatialIndexClass* = ptr TSpatialIndexClass PSpatialIndexClass* = ptr TSpatialIndexClass
TSpatialIndexClass*{.pf.} = object TSpatialIndexClass*{.pf.} = object
@ -286,7 +286,7 @@ type
CP_CIRCLE_SHAPE, CP_SEGMENT_SHAPE, CP_POLY_SHAPE, CP_NUM_SHAPES CP_CIRCLE_SHAPE, CP_SEGMENT_SHAPE, CP_POLY_SHAPE, CP_NUM_SHAPES
TShapeCacheDataImpl* = proc (shape: PShape; p: TVector; rot: TVector): TBB{.cdecl.} TShapeCacheDataImpl* = proc (shape: PShape; p: TVector; rot: TVector): TBB{.cdecl.}
TShapeDestroyImpl* = proc (shape: PShape){.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; TShapeSegmentQueryImpl* = proc (shape: PShape; a: TVector; b: TVector;
info: PSegmentQueryInfo){.cdecl.} info: PSegmentQueryInfo){.cdecl.}
PShapeClass* = ptr TShapeClass PShapeClass* = ptr TShapeClass
@ -427,7 +427,7 @@ defGetter(PSpace, CpFloat, currDt, CurrentTimeStep)
#/ returns true from inside a callback and objects cannot be added/removed. #/ 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 result = space.locked.bool
#/ Set a default collision handler for this space. #/ Set a default collision handler for this space.
@ -478,24 +478,24 @@ proc removeBody*(space: PSpace; body: PBody){.
proc RemoveConstraint*(space: PSpace; constraint: PConstraint){. proc RemoveConstraint*(space: PSpace; constraint: PConstraint){.
cdecl, importc: "cpSpaceRemoveConstraint", dynlib: Lib.} cdecl, importc: "cpSpaceRemoveConstraint", dynlib: Lib.}
#/ Test if a collision shape has been added to the space. #/ 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.} cdecl, importc: "cpSpaceContainsShape", dynlib: Lib.}
#/ Test if a rigid body has been added to the space. #/ 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.} cdecl, importc: "cpSpaceContainsBody", dynlib: Lib.}
#/ Test if a constraint has been added to the space. #/ 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.} cdecl, importc: "cpSpaceContainsConstraint", dynlib: Lib.}
#/ Schedule a post-step callback to be called when cpSpaceStep() finishes. #/ 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 #/ @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){. obj: pointer; data: pointer){.
cdecl, importc: "cpSpaceAddPostStepCallback", dynlib: Lib.} cdecl, importc: "cpSpaceAddPostStepCallback", dynlib: Lib.}
#/ Query the space at a point and call @c func for each shape found. #/ Query the space at a point and call @c func for each shape found.
proc pointQuery*(space: PSpace; point: TVector; layers: TLayers; 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.} cdecl, importc: "cpSpacePointQuery", dynlib: Lib.}
#/ Query the space at a point and return the first shape found. Returns NULL if no shapes were found. #/ 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. #/ 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; proc segmentQuery*(space: PSpace; start: TVector; to: TVector;
layers: TLayers; group: TGroup; layers: TLayers; group: TGroup;
func: TSpaceSegmentQueryFunc; data: pointer){. fun: TSpaceSegmentQueryFunc; data: pointer){.
cdecl, importc: "cpSpaceSegmentQuery", dynlib: Lib.} 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. #/ 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; 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. #/ 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. #/ Only the shape's bounding boxes are checked for overlap, not their full shape.
proc BBQuery*(space: PSpace; bb: TBB; layers: TLayers; group: TGroup; proc BBQuery*(space: PSpace; bb: TBB; layers: TLayers; group: TGroup;
func: TSpaceBBQueryFunc; data: pointer){. fun: TSpaceBBQueryFunc; data: pointer){.
cdecl, importc: "cpSpaceBBQuery", dynlib: Lib.} cdecl, importc: "cpSpaceBBQuery", dynlib: Lib.}
#/ Query a space for any shapes overlapping the given shape and call @c func for each shape found. #/ 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.} cdecl, importc: "cpSpaceShapeQuery", dynlib: Lib.}
#/ Call cpBodyActivate() for any shape that is overlaps the given shape. #/ Call cpBodyActivate() for any shape that is overlaps the given shape.
proc activateShapesTouchingShape*(space: PSpace; shape: PShape){. proc activateShapesTouchingShape*(space: PSpace; shape: PShape){.
cdecl, importc: "cpSpaceActivateShapesTouchingShape", dynlib: Lib.} cdecl, importc: "cpSpaceActivateShapesTouchingShape", dynlib: Lib.}
#/ Call @c func for each body in the space. #/ 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.} cdecl, importc: "cpSpaceEachBody", dynlib: Lib.}
#/ Call @c func for each shape in the space. #/ Call @c func for each shape in the space.
proc eachShape*(space: PSpace; func: TSpaceShapeIteratorFunc; proc eachShape*(space: PSpace; fun: TSpaceShapeIteratorFunc;
data: pointer){. data: pointer){.
cdecl, importc: "cpSpaceEachShape", dynlib: Lib.} cdecl, importc: "cpSpaceEachShape", dynlib: Lib.}
#/ Call @c func for each shape in the space. #/ Call @c func for each shape in the space.
proc eachConstraint*(space: PSpace; func: TSpaceConstraintIteratorFunc; proc eachConstraint*(space: PSpace; fun: TSpaceConstraintIteratorFunc;
data: pointer){. data: pointer){.
cdecl, importc: "cpSpaceEachConstraint", dynlib: Lib.} cdecl, importc: "cpSpaceEachConstraint", dynlib: Lib.}
#/ Update the collision detection info for the static shapes in the space. #/ 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.} = proc distsq*(v1, v2: TVector): CpFloat {.inline.} =
result = (v1 - v2).lenSq #vlengthsq(vsub(v1, v2)) result = (v1 - v2).lenSq #vlengthsq(vsub(v1, v2))
#/ Returns true if the distance between v1 and v2 is less than dist. #/ 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 result = v1.distSq(v2) < dist * dist
@ -706,13 +706,13 @@ proc Sleep*(body: PBody){.importc: "cpBodySleep", dynlib: Lib.}
proc SleepWithGroup*(body: PBody; group: PBody){. proc SleepWithGroup*(body: PBody; group: PBody){.
importc: "cpBodySleepWithGroup", dynlib: Lib.} importc: "cpBodySleepWithGroup", dynlib: Lib.}
#/ Returns true if the body is sleeping. #/ Returns true if the body is sleeping.
proc isSleeping*(body: PBody): Bool {.inline.} = proc isSleeping*(body: PBody): bool {.inline.} =
return body.node.root != nil return body.node.root != nil
#/ Returns true if the body is static. #/ Returns true if the body is static.
proc isStatic*(body: PBody): bool {.inline.} = proc isStatic*(body: PBody): bool {.inline.} =
return body.node.idleTime == CpInfinity return body.node.idleTime == CpInfinity
#/ Returns true if the body has not been added to a space. #/ 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 return body.space == nil
# #define CP_DefineBodyStructGetter(type, member, name) \ # #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) 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. #/ 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){. data: pointer){.
cdecl, importc: "cpBodyEachShape", dynlib: Lib.} cdecl, importc: "cpBodyEachShape", dynlib: Lib.}
#/ Call @c func once for each constraint attached to @c body and added to the space. #/ 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) {. data: pointer) {.
cdecl, importc: "cpBodyEachConstraint", dynlib: Lib.} cdecl, importc: "cpBodyEachConstraint", dynlib: Lib.}
#/ Call @c func once for each arbiter that is currently active on the body. #/ 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){. data: pointer){.
cdecl, importc: "cpBodyEachArbiter", dynlib: Lib.} cdecl, importc: "cpBodyEachArbiter", dynlib: Lib.}
#/ Allocate a spatial hash. #/ Allocate a spatial hash.
@ -824,10 +824,10 @@ proc SpaceHashAlloc*(): PSpaceHash{.
cdecl, importc: "cpSpaceHashAlloc", dynlib: Lib.} cdecl, importc: "cpSpaceHashAlloc", dynlib: Lib.}
#/ Initialize a spatial hash. #/ Initialize a spatial hash.
proc SpaceHashInit*(hash: PSpaceHash; celldim: CpFloat; numcells: cint; proc SpaceHashInit*(hash: PSpaceHash; celldim: CpFloat; numcells: cint;
bbfunc: TSpatialIndexBBFunc; staticIndex: PSpatialIndex): PSpatialIndex{. bbfun: TSpatialIndexBBFunc; staticIndex: PSpatialIndex): PSpatialIndex{.
cdecl, importc: "cpSpaceHashInit", dynlib: Lib.} cdecl, importc: "cpSpaceHashInit", dynlib: Lib.}
#/ Allocate and initialize a spatial hash. #/ 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{. staticIndex: PSpatialIndex): PSpatialIndex{.
cdecl, importc: "cpSpaceHashNew", dynlib: Lib.} cdecl, importc: "cpSpaceHashNew", dynlib: Lib.}
#/ Change the cell dimensions and table size of the spatial hash to tune it. #/ 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. #/ Allocate a bounding box tree.
proc BBTreeAlloc*(): PBBTree{.cdecl, importc: "cpBBTreeAlloc", dynlib: Lib.} proc BBTreeAlloc*(): PBBTree{.cdecl, importc: "cpBBTreeAlloc", dynlib: Lib.}
#/ Initialize a bounding box tree. #/ Initialize a bounding box tree.
proc BBTreeInit*(tree: PBBTree; bbfunc: TSpatialIndexBBFunc; proc BBTreeInit*(tree: PBBTree; bbfun: TSpatialIndexBBFunc;
staticIndex: ptr TSpatialIndex): ptr TSpatialIndex{.cdecl, staticIndex: ptr TSpatialIndex): ptr TSpatialIndex{.cdecl,
importc: "cpBBTreeInit", dynlib: Lib.} importc: "cpBBTreeInit", dynlib: Lib.}
#/ Allocate and initialize a bounding box tree. #/ 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.} cdecl, importc: "cpBBTreeNew", dynlib: Lib.}
#/ Perform a static top down optimization of the tree. #/ Perform a static top down optimization of the tree.
proc BBTreeOptimize*(index: PSpatialIndex){. proc BBTreeOptimize*(index: PSpatialIndex){.
cdecl, importc: "cpBBTreeOptimize", dynlib: Lib.} cdecl, importc: "cpBBTreeOptimize", dynlib: Lib.}
#/ Set the velocity function for the bounding box tree to enable temporal coherence. #/ 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.} cdecl, importc: "cpBBTreeSetVelocityFunc", dynlib: Lib.}
#MARK: Single Axis Sweep #MARK: Single Axis Sweep
@ -864,12 +864,12 @@ proc Sweep1DAlloc*(): ptr TSweep1D{.cdecl, importc: "cpSweep1DAlloc",
dynlib: Lib.} dynlib: Lib.}
#/ Initialize a 1D sort and sweep broadphase. #/ 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, staticIndex: ptr TSpatialIndex): ptr TSpatialIndex{.cdecl,
importc: "cpSweep1DInit", dynlib: Lib.} importc: "cpSweep1DInit", dynlib: Lib.}
#/ Allocate and initialize a 1D sort and sweep broadphase. #/ 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.} cdecl, importc: "cpSweep1DNew", dynlib: Lib.}
@ -1359,7 +1359,7 @@ defCProp(SlideJoint, TVector, anchr2, Anchr2)
defCProp(SlideJoint, CpFloat, min, Min) defCProp(SlideJoint, CpFloat, min, Min)
defCProp(SlideJoint, CpFloat, max, Max) defCProp(SlideJoint, CpFloat, max, Max)
proc pivotJointGetClass*(): PConstraintClass {. proc PivotJointGetClass*(): PConstraintClass {.
cdecl, importc: "cpPivotJointGetClass", dynlib: Lib.} cdecl, importc: "cpPivotJointGetClass", dynlib: Lib.}
#/ Allocate a pivot joint #/ Allocate a pivot joint

View file

@ -20,7 +20,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
const Lib = "libenet.so.1(|.0.3)" const Lib = "libenet.so.1(|.0.3)"
{.deadCodeElim: ON.} {.deadCodeElim: on.}
const const
ENET_VERSION_MAJOR* = 1 ENET_VERSION_MAJOR* = 1
ENET_VERSION_MINOR* = 3 ENET_VERSION_MINOR* = 3

View file

@ -9,15 +9,6 @@ template defPacketImports*(): stmt {.immediate, dirty.} =
import macros, macro_dsl, estreams import macros, macro_dsl, estreams
from strutils import format 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.} = macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} =
result = newNimNode(nnkStmtList) result = newNimNode(nnkStmtList)
let let

View file

@ -221,10 +221,10 @@ type
TTransform* {.pf.} = object TTransform* {.pf.} = object
matrix*: array[0..8, cfloat] matrix*: array[0..8, cfloat]
TColor* {.pf.} = object TColor* {.pf.} = object
r*: Uint8 r*: uint8
g*: Uint8 g*: uint8
b*: Uint8 b*: uint8
a*: Uint8 a*: uint8
PFloatRect* = ptr TFloatRect PFloatRect* = ptr TFloatRect
TFloatRect*{.pf.} = object TFloatRect*{.pf.} = object
left*: cfloat left*: cfloat
@ -306,7 +306,7 @@ proc close*(window: PRenderWindow) {.
proc isOpen*(window: PRenderWindow): bool {. proc isOpen*(window: PRenderWindow): bool {.
cdecl, importc: "sfRenderWindow_isOpen", dynlib: LibG.} 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]) {. #proc setIcon*(window: PRenderWindow, width, height: cint, pixels: seq[uint8]) {.
# cdecl, importc: "sfRenderWindow_setIcon", dynlib: LibG.} # cdecl, importc: "sfRenderWindow_setIcon", dynlib: LibG.}
@ -395,7 +395,7 @@ proc capture*(window: PRenderWindow): PImage {.
cdecl, importc: "sfRenderWindow_capture", dynlib: LibG.} cdecl, importc: "sfRenderWindow_capture", dynlib: LibG.}
#Construct a new render texture #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.} cdecl, importc: "sfRenderTexture_create", dynlib: LibG.}
#Destroy an existing render texture #Destroy an existing render texture
proc destroy*(renderTexture: PRenderTexture){. proc destroy*(renderTexture: PRenderTexture){.
@ -522,9 +522,9 @@ proc copy*(font: PFont): PFont {.
cdecl, importc: "sfFont_copy", dynlib: LibG.} cdecl, importc: "sfFont_copy", dynlib: LibG.}
proc destroy*(font: PFont) {. proc destroy*(font: PFont) {.
cdecl, importc: "sfFont_destroy", dynlib: LibG.} 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.} 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.} cdecl, importc: "sfFont_getKerning", dynlib: LibG.}
proc getLineSpacing*(font: PFont, characterSize: cint): cint {. proc getLineSpacing*(font: PFont, characterSize: cint): cint {.
cdecl, importc: "sfFont_getLineSpacing", dynlib: LibG.} cdecl, importc: "sfFont_getLineSpacing", dynlib: LibG.}
@ -882,7 +882,7 @@ proc getInverseTransform*(text: PText): TTransform {.
cdecl, importc: "sfText_getInverseTransform", dynlib: LibG.} cdecl, importc: "sfText_getInverseTransform", dynlib: LibG.}
proc setString*(text: PText, string: cstring) {. proc setString*(text: PText, string: cstring) {.
cdecl, importc: "sfText_setString", dynlib: LibG.} 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.} cdecl, importc: "sfText_setUnicodeString", dynlib: LibG.}
proc setFont*(text: PText, font: PFont) {. proc setFont*(text: PText, font: PFont) {.
cdecl, importc: "sfText_setFont", dynlib: LibG.} cdecl, importc: "sfText_setFont", dynlib: LibG.}
@ -894,13 +894,13 @@ proc setColor*(text: PText, color: TColor) {.
cdecl, importc: "sfText_setColor", dynlib: LibG.} cdecl, importc: "sfText_setColor", dynlib: LibG.}
proc getString*(text: PText): cstring {. proc getString*(text: PText): cstring {.
cdecl, importc: "sfText_getString", dynlib: LibG.} 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.} importc: "sfText_getUnicodeString", dynlib: LibG.}
proc getFont*(text: PText): PFont {. proc getFont*(text: PText): PFont {.
cdecl, importc: "sfText_getFont", dynlib: LibG.} cdecl, importc: "sfText_getFont", dynlib: LibG.}
proc getCharacterSize*(text: PText): cint {. proc getCharacterSize*(text: PText): cint {.
cdecl, importc: "sfText_getCharacterSize", dynlib: LibG.} cdecl, importc: "sfText_getCharacterSize", dynlib: LibG.}
proc getStyle*(text: PText): Uint32 {. proc getStyle*(text: PText): uint32 {.
cdecl, importc: "sfText_getStyle", dynlib: LibG.} cdecl, importc: "sfText_getStyle", dynlib: LibG.}
proc getColor*(text: PText): TColor {. proc getColor*(text: PText): TColor {.
cdecl, importc: "sfText_getColor", dynlib: LibG.} cdecl, importc: "sfText_getColor", dynlib: LibG.}

View file

@ -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 #/ \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 #/ 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 samples Pointer to the array of samples in memory
#/ \param sampleCount Number of samples in the array #/ \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 #/ \brief Get the array of audio samples stored in a sound buffer
#/ #/
#/ The format of the returned samples is 16 bits signed integer #/ 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. #/ is given by the sfSoundBuffer_getSampleCount function.
#/ #/
#/ \param soundBuffer Sound buffer object #/ \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 #/ \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.} cdecl, importc: "sfSoundBuffer_getSamples", dynlib: Lib.}
#////////////////////////////////////////////////////////// #//////////////////////////////////////////////////////////
#/ \brief Get the number of samples stored in a sound buffer #/ \brief Get the number of samples stored in a sound buffer

View file

@ -105,6 +105,7 @@ proc tryLogin*(b: PButton) =
passwd = u_passwd.getText()) passwd = u_passwd.getText())
dirServer.send HLogin, login dirServer.send HLogin, login
proc tryTransition*(b: PButton) = proc tryTransition*(b: PButton) =
discard
#zone.writePkt HZoneJoinReq, myCreds #zone.writePkt HZoneJoinReq, myCreds
proc tryConnect*(b: PButton) = proc tryConnect*(b: PButton) =
if not dirServer.connected: if not dirServer.connected:

View file

@ -143,7 +143,7 @@ proc mouseToSpace*(): TVector =
proc explode*(b: PLiveBullet) proc explode*(b: PLiveBullet)
## TCollisionBeginFunc ## TCollisionBeginFunc
proc collisionBulletPlayer(arb: PArbiter; space: PSpace; proc collisionBulletPlayer(arb: PArbiter; space: PSpace;
data: pointer): Bool{.cdecl.} = data: pointer): bool{.cdecl.} =
var var
bullet = cast[PLiveBullet](arb.a.data) bullet = cast[PLiveBullet](arb.a.data)
target = cast[PVehicle](arb.b.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.} = proc angularDampingSim(body: PBody, gravity: TVector, damping, dt: CpFloat){.cdecl.} =
body.w -= (body.w * 0.98 * dt) body.w -= (body.w * 0.98 * dt)
body.updateVelocity(gravity, damping, dt) body.UpdateVelocity(gravity, damping, dt)
proc initLevel() = proc initLevel() =
loadAllAssets() loadAllAssets()
@ -227,7 +227,7 @@ proc explode*(b: PLiveBullet) =
playSound(b.record.explosion.sound, b.body.getPos()) playSound(b.record.explosion.sound, b.body.getPos())
proc bulletUpdate(body: PBody, gravity: TVector, damping, dt: CpFloat){.cdecl.} = proc bulletUpdate(body: PBody, gravity: TVector, damping, dt: CpFloat){.cdecl.} =
body.updateVelocity(gravity, damping, dt) body.UpdateVelocity(gravity, damping, dt)
template getPhysical() {.immediate.} = template getPhysical() {.immediate.} =
result.body = space.addBody(newBody( result.body = space.addBody(newBody(
@ -237,7 +237,7 @@ template getPhysical() {.immediate.} =
chipmunk.newCircleShape( chipmunk.newCircleShape(
result.body, result.body,
record.physics.radius, record.physics.radius,
vectorZero)) VectorZero))
proc newBullet*(record: PBulletRecord; fromPlayer: PPlayer): PLiveBullet = proc newBullet*(record: PBulletRecord; fromPlayer: PPlayer): PLiveBullet =
new(result, free) new(result, free)
@ -480,7 +480,7 @@ when defined(DebugKeys):
echo(repr(activeVehicle.record)) echo(repr(activeVehicle.record))
elif keyPressed(KeyH): elif keyPressed(KeyH):
activeVehicle.body.setPos(vector(100.0, 100.0)) activeVehicle.body.setPos(vector(100.0, 100.0))
activeVehicle.body.setVel(vectorZero) activeVehicle.body.setVel(VectorZero)
elif keyPressed(KeyComma): elif keyPressed(KeyComma):
activeVehicle.body.setPos mouseToSpace()) activeVehicle.body.setPos mouseToSpace())
ingameClient.registerHandler(KeyY, down, proc() = ingameClient.registerHandler(KeyY, down, proc() =
@ -507,7 +507,7 @@ when defined(DebugKeys):
return return
let body = shape.getBody() let body = shape.getBody()
mouseJoint = space.addConstraint( mouseJoint = space.addConstraint(
newPivotJoint(mouseBody, body, vectorZero, body.world2local(point))) newPivotJoint(mouseBody, body, VectorZero, body.world2local(point)))
mouseJoint.maxForce = 50000.0 mouseJoint.maxForce = 50000.0
mouseJoint.errorBias = pow(1.0 - 0.15, 60)) mouseJoint.errorBias = pow(1.0 - 0.15, 60))
@ -539,15 +539,15 @@ proc mainUpdate(dt: float) =
elif not activeVehicle.isNil: elif not activeVehicle.isNil:
if keyPressed(KeyUp): if keyPressed(KeyUp):
activeVehicle.accel(dt) activeVehicle.accel(dt)
elif keyPressed(keyDown): elif keyPressed(KeyDown):
activeVehicle.reverse(dt) activeVehicle.reverse(dt)
if keyPressed(KeyRight): if keyPressed(KeyRight):
activeVehicle.turn_right(dt) activeVehicle.turn_right(dt)
elif keyPressed(KeyLeft): elif keyPressed(KeyLeft):
activeVehicle.turn_left(dt) activeVehicle.turn_left(dt)
if keyPressed(keyz): if keyPressed(Keyz):
activeVehicle.strafe_left(dt) activeVehicle.strafe_left(dt)
elif keyPressed(keyx): elif keyPressed(Keyx):
activeVehicle.strafe_right(dt) activeVehicle.strafe_right(dt)
if keyPressed(KeyLControl): if keyPressed(KeyLControl):
localPlayer.useItem 0 localPlayer.useItem 0
@ -557,7 +557,7 @@ proc mainUpdate(dt: float) =
localPlayer.useItem 2 localPlayer.useItem 2
if keyPressed(KeyW): if keyPressed(KeyW):
localPlayer.useItem 3 localPlayer.useItem 3
if Keypressed(keyA): if keyPressed(KeyA):
localPlayer.useItem 4 localPlayer.useItem 4
if keyPressed(sfml.KeyS): if keyPressed(sfml.KeyS):
localPlayer.useItem 5 localPlayer.useItem 5
@ -666,7 +666,7 @@ when isMainModule:
import parseopt import parseopt
localPlayer = newPlayer() localPlayer = newPlayer()
LobbyInit() lobbyInit()
videoMode = getClientSettings().resolution videoMode = getClientSettings().resolution
window = newRenderWindow(videoMode, "sup", sfDefaultStyle) window = newRenderWindow(videoMode, "sup", sfDefaultStyle)
@ -683,7 +683,7 @@ when isMainModule:
mouseSprite.setOutlineThickness 1.4 mouseSprite.setOutlineThickness 1.4
mouseSprite.setOrigin vec2f(14, 14) mouseSprite.setOrigin vec2f(14, 14)
LobbyReady() lobbyReady()
playBtn = specGui.newButton( playBtn = specGui.newButton(
"Unspec - F12", position = vec2f(680.0, 8.0), onClick = proc(b: PButton) = "Unspec - F12", position = vec2f(680.0, 8.0), onClick = proc(b: PButton) =
toggleSpec()) toggleSpec())

View file

@ -26,7 +26,7 @@ proc newObject*(record: PObjectRecord): PGameObject =
when false: when false:
result.sprite = record.anim.spriteSheet.sprite.copy() result.sprite = record.anim.spriteSheet.sprite.copy()
result.body = newBody(result.record.physics.mass, 10.0) 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)) result.body.setPos(vector(100, 100))
proc newObject*(name: string): PGameObject = proc newObject*(name: string): PGameObject =
result = newObject(fetchObj(name)) result = newObject(fetchObj(name))

View file

@ -38,7 +38,7 @@ type
PGLclampf* = ptr TGLclampf PGLclampf* = ptr TGLclampf
PGLdouble* = ptr TGLdouble PGLdouble* = ptr TGLdouble
PGLclampd* = ptr TGLclampd PGLclampd* = ptr TGLclampd
PGLvoid* = Pointer PGLvoid* = pointer
PPGLvoid* = ptr PGLvoid PPGLvoid* = ptr PGLvoid
TGLenum* = cint TGLenum* = cint
TGLboolean* = bool TGLboolean* = bool
@ -983,7 +983,7 @@ const # Version
GL_TEXTURE_COMPONENTS* = GL_TEXTURE_INTERNAL_FORMAT GL_TEXTURE_COMPONENTS* = GL_TEXTURE_INTERNAL_FORMAT
proc glAccum*(op: TGLenum, value: TGLfloat){.dynlib: dllname, importc: "glAccum".} 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".} importc: "glAlphaFunc".}
proc glAreTexturesResident*(n: TGLsizei, textures: PGLuint, proc glAreTexturesResident*(n: TGLsizei, textures: PGLuint,
residences: PGLboolean): TGLboolean{. residences: PGLboolean): TGLboolean{.
@ -998,7 +998,7 @@ proc glBitmap*(width, height: TGLsizei, xorig, yorig: TGLfloat,
proc glBlendFunc*(sfactor, dfactor: TGLenum){.dynlib: dllname, proc glBlendFunc*(sfactor, dfactor: TGLenum){.dynlib: dllname,
importc: "glBlendFunc".} importc: "glBlendFunc".}
proc glCallList*(list: TGLuint){.dynlib: dllname, importc: "glCallList".} 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".} importc: "glCallLists".}
proc glClear*(mask: TGLbitfield){.dynlib: dllname, importc: "glClear".} proc glClear*(mask: TGLbitfield){.dynlib: dllname, importc: "glClear".}
proc glClearAccum*(red, green, blue, alpha: TGLfloat){.dynlib: dllname, 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, proc glColorMaterial*(face, mode: TGLenum){.dynlib: dllname,
importc: "glColorMaterial".} importc: "glColorMaterial".}
proc glColorPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei, proc glColorPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei,
pointer: Pointer){.dynlib: dllname, p: pointer){.dynlib: dllname,
importc: "glColorPointer".} importc: "glColorPointer".}
proc glCopyPixels*(x, y: TGLint, width, height: TGLsizei, atype: TGLenum){. proc glCopyPixels*(x, y: TGLint, width, height: TGLsizei, atype: TGLenum){.
dynlib: dllname, importc: "glCopyPixels".} dynlib: dllname, importc: "glCopyPixels".}
@ -1084,7 +1084,7 @@ proc glDeleteLists*(list: TGLuint, range: TGLsizei){.dynlib: dllname,
importc: "glDeleteLists".} importc: "glDeleteLists".}
proc glDeleteTextures*(n: TGLsizei, textures: PGLuint){.dynlib: dllname, proc glDeleteTextures*(n: TGLsizei, textures: PGLuint){.dynlib: dllname,
importc: "glDeleteTextures".} 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 glDepthMask*(flag: TGLboolean){.dynlib: dllname, importc: "glDepthMask".}
proc glDepthRange*(zNear, zFar: TGLclampd){.dynlib: dllname, proc glDepthRange*(zNear, zFar: TGLclampd){.dynlib: dllname,
importc: "glDepthRange".} importc: "glDepthRange".}
@ -1095,12 +1095,12 @@ proc glDrawArrays*(mode: TGLenum, first: TGLint, count: TGLsizei){.
dynlib: dllname, importc: "glDrawArrays".} dynlib: dllname, importc: "glDrawArrays".}
proc glDrawBuffer*(mode: TGLenum){.dynlib: dllname, importc: "glDrawBuffer".} proc glDrawBuffer*(mode: TGLenum){.dynlib: dllname, importc: "glDrawBuffer".}
proc glDrawElements*(mode: TGLenum, count: TGLsizei, atype: TGLenum, proc glDrawElements*(mode: TGLenum, count: TGLsizei, atype: TGLenum,
indices: Pointer){.dynlib: dllname, indices: pointer){.dynlib: dllname,
importc: "glDrawElements".} importc: "glDrawElements".}
proc glDrawPixels*(width, height: TGLsizei, format, atype: TGLenum, 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 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".} importc: "glEdgeFlagPointer".}
proc glEdgeFlagv*(flag: PGLboolean){.dynlib: dllname, importc: "glEdgeFlagv".} proc glEdgeFlagv*(flag: PGLboolean){.dynlib: dllname, importc: "glEdgeFlagv".}
proc glEnable*(cap: TGLenum){.dynlib: dllname, importc: "glEnable".} proc glEnable*(cap: TGLenum){.dynlib: dllname, importc: "glEnable".}
@ -1171,7 +1171,7 @@ proc glGetPixelMapuiv*(map: TGLenum, values: PGLuint){.dynlib: dllname,
importc: "glGetPixelMapuiv".} importc: "glGetPixelMapuiv".}
proc glGetPixelMapusv*(map: TGLenum, values: PGLushort){.dynlib: dllname, proc glGetPixelMapusv*(map: TGLenum, values: PGLushort){.dynlib: dllname,
importc: "glGetPixelMapusv".} importc: "glGetPixelMapusv".}
proc glGetPointerv*(pname: TGLenum, params: Pointer){.dynlib: dllname, proc glGetPointerv*(pname: TGLenum, params: pointer){.dynlib: dllname,
importc: "glGetPointerv".} importc: "glGetPointerv".}
proc glGetPolygonStipple*(mask: PGLubyte){.dynlib: dllname, proc glGetPolygonStipple*(mask: PGLubyte){.dynlib: dllname,
importc: "glGetPolygonStipple".} importc: "glGetPolygonStipple".}
@ -1188,10 +1188,10 @@ proc glGetTexGenfv*(coord, pname: TGLenum, params: PGLfloat){.dynlib: dllname,
proc glGetTexGeniv*(coord, pname: TGLenum, params: PGLint){.dynlib: dllname, proc glGetTexGeniv*(coord, pname: TGLenum, params: PGLint){.dynlib: dllname,
importc: "glGetTexGeniv".} importc: "glGetTexGeniv".}
proc glGetTexImage*(target: TGLenum, level: TGLint, format: TGLenum, proc glGetTexImage*(target: TGLenum, level: TGLint, format: TGLenum,
atype: TGLenum, pixels: Pointer){.dynlib: dllname, atype: TGLenum, pixels: pointer){.dynlib: dllname,
importc: "glGetTexImage".} importc: "glGetTexImage".}
proc glGetTexLevelParameterfv*(target: TGLenum, level: TGLint, pname: TGLenum, proc glGetTexLevelParameterfv*(target: TGLenum, level: TGLint, pname: TGLenum,
params: Pointer){.dynlib: dllname, params: pointer){.dynlib: dllname,
importc: "glGetTexLevelParameterfv".} importc: "glGetTexLevelParameterfv".}
proc glGetTexLevelParameteriv*(target: TGLenum, level: TGLint, pname: TGLenum, proc glGetTexLevelParameteriv*(target: TGLenum, level: TGLint, pname: TGLenum,
params: PGLint){.dynlib: dllname, params: PGLint){.dynlib: dllname,
@ -1202,7 +1202,7 @@ proc glGetTexParameteriv*(target, pname: TGLenum, params: PGLint){.
dynlib: dllname, importc: "glGetTexParameteriv".} dynlib: dllname, importc: "glGetTexParameteriv".}
proc glHint*(target, mode: TGLenum){.dynlib: dllname, importc: "glHint".} proc glHint*(target, mode: TGLenum){.dynlib: dllname, importc: "glHint".}
proc glIndexMask*(mask: TGLuint){.dynlib: dllname, importc: "glIndexMask".} 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".} dynlib: dllname, importc: "glIndexPointer".}
proc glIndexd*(c: TGLdouble){.dynlib: dllname, importc: "glIndexd".} proc glIndexd*(c: TGLdouble){.dynlib: dllname, importc: "glIndexd".}
proc glIndexdv*(c: PGLdouble){.dynlib: dllname, importc: "glIndexdv".} 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 glIndexub*(c: TGLubyte){.dynlib: dllname, importc: "glIndexub".}
proc glIndexubv*(c: PGLubyte){.dynlib: dllname, importc: "glIndexubv".} proc glIndexubv*(c: PGLubyte){.dynlib: dllname, importc: "glIndexubv".}
proc glInitNames*(){.dynlib: dllname, importc: "glInitNames".} 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".} dynlib: dllname, importc: "glInterleavedArrays".}
proc glIsEnabled*(cap: TGLenum): TGLboolean{.dynlib: dllname, proc glIsEnabled*(cap: TGLenum): TGLboolean{.dynlib: dllname,
importc: "glIsEnabled".} 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 glNormal3iv*(v: PGLint){.dynlib: dllname, importc: "glNormal3iv".}
proc glNormal3s*(nx, ny, nz: TGLshort){.dynlib: dllname, importc: "glNormal3s".} proc glNormal3s*(nx, ny, nz: TGLshort){.dynlib: dllname, importc: "glNormal3s".}
proc glNormal3sv*(v: PGLshort){.dynlib: dllname, importc: "glNormal3sv".} 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".} dynlib: dllname, importc: "glNormalPointer".}
proc glOrtho*(left, right, bottom, top, zNear, zFar: TGLdouble){. proc glOrtho*(left, right, bottom, top, zNear, zFar: TGLdouble){.
dynlib: dllname, importc: "glOrtho".} 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 glRasterPos4sv*(v: PGLshort){.dynlib: dllname, importc: "glRasterPos4sv".}
proc glReadBuffer*(mode: TGLenum){.dynlib: dllname, importc: "glReadBuffer".} proc glReadBuffer*(mode: TGLenum){.dynlib: dllname, importc: "glReadBuffer".}
proc glReadPixels*(x, y: TGLint, width, height: TGLsizei, proc glReadPixels*(x, y: TGLint, width, height: TGLsizei,
format, atype: TGLenum, pixels: Pointer){.dynlib: dllname, format, atype: TGLenum, pixels: pointer){.dynlib: dllname,
importc: "glReadPixels".} importc: "glReadPixels".}
proc glRectd*(x1, y1, x2, y2: TGLdouble){.dynlib: dllname, importc: "glRectd".} proc glRectd*(x1, y1, x2, y2: TGLdouble){.dynlib: dllname, importc: "glRectd".}
proc glRectdv*(v1: PGLdouble, v2: PGLdouble){.dynlib: dllname, 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, proc glSelectBuffer*(size: TGLsizei, buffer: PGLuint){.dynlib: dllname,
importc: "glSelectBuffer".} importc: "glSelectBuffer".}
proc glShadeModel*(mode: TGLenum){.dynlib: dllname, importc: "glShadeModel".} 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".} dynlib: dllname, importc: "glStencilFunc".}
proc glStencilMask*(mask: TGLuint){.dynlib: dllname, importc: "glStencilMask".} proc glStencilMask*(mask: TGLuint){.dynlib: dllname, importc: "glStencilMask".}
proc glStencilOp*(fail, zfail, zpass: TGLenum){.dynlib: dllname, proc glStencilOp*(fail, zfail, zpass: TGLenum){.dynlib: dllname,
@ -1424,7 +1424,7 @@ proc glTexCoord4s*(s, t, r, q: TGLshort){.dynlib: dllname,
importc: "glTexCoord4s".} importc: "glTexCoord4s".}
proc glTexCoord4sv*(v: PGLshort){.dynlib: dllname, importc: "glTexCoord4sv".} proc glTexCoord4sv*(v: PGLshort){.dynlib: dllname, importc: "glTexCoord4sv".}
proc glTexCoordPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei, proc glTexCoordPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei,
pointer: Pointer){.dynlib: dllname, p: pointer){.dynlib: dllname,
importc: "glTexCoordPointer".} importc: "glTexCoordPointer".}
proc glTexEnvf*(target: TGLenum, pname: TGLenum, param: TGLfloat){. proc glTexEnvf*(target: TGLenum, pname: TGLenum, param: TGLfloat){.
dynlib: dllname, importc: "glTexEnvf".} dynlib: dllname, importc: "glTexEnvf".}
@ -1448,10 +1448,10 @@ proc glTexGeniv*(coord: TGLenum, pname: TGLenum, params: PGLint){.
dynlib: dllname, importc: "glTexGeniv".} dynlib: dllname, importc: "glTexGeniv".}
proc glTexImage1D*(target: TGLenum, level, internalformat: TGLint, proc glTexImage1D*(target: TGLenum, level, internalformat: TGLint,
width: TGLsizei, border: TGLint, format, atype: TGLenum, 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, proc glTexImage2D*(target: TGLenum, level, internalformat: TGLint,
width, height: TGLsizei, border: TGLint, width, height: TGLsizei, border: TGLint,
format, atype: TGLenum, pixels: Pointer){.dynlib: dllname, format, atype: TGLenum, pixels: pointer){.dynlib: dllname,
importc: "glTexImage2D".} importc: "glTexImage2D".}
proc glTexParameterf*(target: TGLenum, pname: TGLenum, param: TGLfloat){. proc glTexParameterf*(target: TGLenum, pname: TGLenum, param: TGLfloat){.
dynlib: dllname, importc: "glTexParameterf".} dynlib: dllname, importc: "glTexParameterf".}
@ -1462,11 +1462,11 @@ proc glTexParameteri*(target: TGLenum, pname: TGLenum, param: TGLint){.
proc glTexParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){. proc glTexParameteriv*(target: TGLenum, pname: TGLenum, params: PGLint){.
dynlib: dllname, importc: "glTexParameteriv".} dynlib: dllname, importc: "glTexParameteriv".}
proc glTexSubImage1D*(target: TGLenum, level, xoffset: TGLint, width: TGLsizei, 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".} importc: "glTexSubImage1D".}
proc glTexSubImage2D*(target: TGLenum, level, xoffset, yoffset: TGLint, proc glTexSubImage2D*(target: TGLenum, level, xoffset, yoffset: TGLint,
width, height: TGLsizei, format, atype: TGLenum, width, height: TGLsizei, format, atype: TGLenum,
pixels: Pointer){.dynlib: dllname, pixels: pointer){.dynlib: dllname,
importc: "glTexSubImage2D".} importc: "glTexSubImage2D".}
proc glTranslated*(x, y, z: TGLdouble){.dynlib: dllname, importc: "glTranslated".} proc glTranslated*(x, y, z: TGLdouble){.dynlib: dllname, importc: "glTranslated".}
proc glTranslatef*(x, y, z: TGLfloat){.dynlib: dllname, importc: "glTranslatef".} 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 glVertex4s*(x, y, z, w: TGLshort){.dynlib: dllname, importc: "glVertex4s".}
proc glVertex4sv*(v: PGLshort){.dynlib: dllname, importc: "glVertex4sv".} proc glVertex4sv*(v: PGLshort){.dynlib: dllname, importc: "glVertex4sv".}
proc glVertexPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei, proc glVertexPointer*(size: TGLint, atype: TGLenum, stride: TGLsizei,
pointer: Pointer){.dynlib: dllname, p: pointer){.dynlib: dllname,
importc: "glVertexPointer".} importc: "glVertexPointer".}
proc glViewport*(x, y: TGLint, width, height: TGLsizei){.dynlib: dllname, proc glViewport*(x, y: TGLint, width, height: TGLsizei){.dynlib: dllname,
importc: "glViewport".} importc: "glViewport".}
@ -1505,28 +1505,28 @@ type
count: TGLsizei) count: TGLsizei)
PFN_GLVERTEX_POINTER_EXTPROC* = proc (size: TGLint, atype: TGLenum, PFN_GLVERTEX_POINTER_EXTPROC* = proc (size: TGLint, atype: TGLenum,
stride, count: TGLsizei, stride, count: TGLsizei,
pointer: Pointer) p: pointer)
PFN_GLNORMAL_POINTER_EXTPROC* = proc (atype: TGLenum, stride, count: TGLsizei, PFN_GLNORMAL_POINTER_EXTPROC* = proc (atype: TGLenum, stride, count: TGLsizei,
pointer: Pointer) p: pointer)
PFN_GLCOLOR_POINTER_EXTPROC* = proc (size: TGLint, atype: TGLenum, 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, PFN_GLINDEX_POINTER_EXTPROC* = proc (atype: TGLenum, stride, count: TGLsizei,
pointer: Pointer) p: pointer)
PFN_GLTEXCOORD_POINTER_EXTPROC* = proc (size: TGLint, atype: TGLenum, 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, PFN_GLEDGEFLAG_POINTER_EXTPROC* = proc (stride, count: TGLsizei,
pointer: PGLboolean) 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, 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_GLADDSWAPHINT_RECT_WINPROC* = proc (x, y: TGLint, width, height: TGLsizei)
PFN_GLCOLOR_TABLE_EXTPROC* = proc (target, internalFormat: TGLenum, PFN_GLCOLOR_TABLE_EXTPROC* = proc (target, internalFormat: TGLenum,
width: TGLsizei, format, atype: TGLenum, width: TGLsizei, format, atype: TGLenum,
data: Pointer) data: pointer)
PFN_GLCOLOR_SUBTABLE_EXTPROC* = proc (target: TGLenum, start, count: TGLsizei, 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, PFN_GLGETCOLOR_TABLE_EXTPROC* = proc (target, format, atype: TGLenum,
data: Pointer) data: pointer)
PFN_GLGETCOLOR_TABLE_PARAMETER_IVEXTPROC* = proc (target, pname: TGLenum, PFN_GLGETCOLOR_TABLE_PARAMETER_IVEXTPROC* = proc (target, pname: TGLenum,
params: PGLint) params: PGLint)
PFN_GLGETCOLOR_TABLE_PARAMETER_FVEXTPROC* = proc (target, pname: TGLenum, PFN_GLGETCOLOR_TABLE_PARAMETER_FVEXTPROC* = proc (target, pname: TGLenum,

View file

@ -4,14 +4,14 @@ template filterIt2*(seq, pred: expr, body: stmt): stmt {.immediate, dirty.} =
for it in items(seq): for it in items(seq):
if pred: body 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 = @[] result = @[]
for item in x.items: 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: 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.} = template unless*(condition: expr; body: stmt): stmt {.dirty.} =
if not(condition): if not(condition):

View file

@ -122,9 +122,9 @@ var
nameToBulletID*: TTable[string, int] nameToBulletID*: TTable[string, int]
activeState = Lobby 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 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 load*(s: PSoundRecord): bool {.discardable.}
proc validateSettings*(settings: PJsonNode; errors: var seq[string]): bool 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 importBullet(data: PJsonNode; errors: var seq[string]): PBulletRecord
proc importSoul(data: PJsonNode): TSoulRecord proc importSoul(data: PJsonNode): TSoulRecord
proc importExplosion(data: PJsonNode; errors: var seq[string]): TExplosionRecord 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 ## this is the only pipe between lobby and main.nim
proc getActiveState*(): TGameState = proc getActiveState*(): TGameState =
@ -466,7 +466,7 @@ proc importPhys(data: PJsonNode): TPhysicsRecord =
phys.getField("radius", result.radius) phys.getField("radius", result.radius)
phys.getField("mass", result.mass) phys.getField("mass", result.mass)
when not defined(NoChipmunk): 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 = proc importHandling(data: PJsonNode): THandlingRecord =
result.thrust = 45.0 result.thrust = 45.0
result.topSpeed = 100.0 #unused result.topSpeed = 100.0 #unused

View file

@ -9,8 +9,8 @@ template idpacket(pktName, id, s2c, c2s: expr): stmt {.immediate, dirty.} =
defPacket(`Sc pktName`, s2c) defPacket(`Sc pktName`, s2c)
defPacket(`Cs pktName`, c2s) defPacket(`Cs pktName`, c2s)
forwardPacketT(Uint8, int8) forwardPacketT(uint8, int8)
forwardPacketT(Uint16, int16) forwardPacketT(uint16, int16)
forwardPacketT(TPort, int16) forwardPacketT(TPort, int16)
idPacket(Login, 'a', idPacket(Login, 'a',
@ -51,7 +51,7 @@ defPacket(ScTeamList, tuple[teams: seq[ScTeam]])
let HTeamChange* = 't' let HTeamChange* = 't'
idPacket(ZoneQuery, 'Q', 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']) tuple[pad: char = '\0'])
type SpawnKind = enum type SpawnKind = enum

View file

@ -9,22 +9,22 @@ proc accel*(obj: PVehicle, dt: float) =
# sin(obj.angle) * obj.record.handling.thrust.float * dt) # sin(obj.angle) * obj.record.handling.thrust.float * dt)
obj.body.applyImpulse( obj.body.applyImpulse(
vectorForAngle(obj.body.getAngle()) * dt * obj.record.handling.thrust, vectorForAngle(obj.body.getAngle()) * dt * obj.record.handling.thrust,
vectorZero) VectorZero)
proc reverse*(obj: PVehicle, dt: float) = proc reverse*(obj: PVehicle, dt: float) =
#obj.velocity += vec2f( #obj.velocity += vec2f(
# -cos(obj.angle) * obj.record.handling.reverse.float * dt, # -cos(obj.angle) * obj.record.handling.reverse.float * dt,
# -sin(obj.angle) * obj.record.handling.reverse.float * dt) # -sin(obj.angle) * obj.record.handling.reverse.float * dt)
obj.body.applyImpulse( obj.body.applyImpulse(
-vectorForAngle(obj.body.getAngle()) * dt * obj.record.handling.reverse, -vectorForAngle(obj.body.getAngle()) * dt * obj.record.handling.reverse,
vectorZero) VectorZero)
proc strafe_left*(obj: PVehicle, dt: float) = proc strafe_left*(obj: PVehicle, dt: float) =
obj.body.applyImpulse( obj.body.applyImpulse(
vectorForAngle(obj.body.getAngle()).perp() * obj.record.handling.strafe * dt, vectorForAngle(obj.body.getAngle()).perp() * obj.record.handling.strafe * dt,
vectorZero) VectorZero)
proc strafe_right*(obj: PVehicle, dt: float) = proc strafe_right*(obj: PVehicle, dt: float) =
obj.body.applyImpulse( obj.body.applyImpulse(
vectorForAngle(obj.body.getAngle()).rperp()* obj.record.handling.strafe * dt, vectorForAngle(obj.body.getAngle()).rperp()* obj.record.handling.strafe * dt,
vectorZero) VectorZero)
proc turn_right*(obj: PVehicle, dt: float) = proc turn_right*(obj: PVehicle, dt: float) =
#obj.angle = (obj.angle + (obj.record.handling.rotation.float / 10.0 * dt)) mod TAU #obj.angle = (obj.angle + (obj.record.handling.rotation.float / 10.0 * dt)) mod TAU
obj.body.setTorque(obj.record.handling.rotation) obj.body.setTorque(obj.record.handling.rotation)

View file

@ -1,3 +1,7 @@
discard """
errormsg: "expression 'generate(builder)' has no type (or is ambiguous)"
"""
# bug #898 # bug #898
proc measureTime(e: auto) = proc measureTime(e: auto) =

View file

@ -30,7 +30,7 @@ accept bar(vbar)
accept baz(vbar) accept baz(vbar)
accept baz(vbaz) accept baz(vbaz)
reject baz(vnotbaz) #reject baz(vnotbaz) # XXX this really shouldn't compile
reject bar(vfoo) reject bar(vfoo)
# https://github.com/Araq/Nim/issues/517 # https://github.com/Araq/Nim/issues/517

View file

@ -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

View file

@ -14,6 +14,7 @@ AST b
20Test 20Test
20 20
''' '''
disabled: true
""" """
import macros import macros

View file

@ -1,6 +1,7 @@
discard """ discard """
msg: "int\nstring\nTBar[int]" msg: "int\nstring\nTBar[int]"
output: "int\nstring\nTBar[int]\nint\nrange 0..2(int)\nstring" output: "int\nstring\nTBar[int]\nint\nrange 0..2(int)\nstring"
disabled: true
""" """
import typetraits import typetraits

View file

@ -1,6 +1,7 @@
discard """ discard """
errormsg: "type mismatch: got (string) but expected 'ptr'" errormsg: "type mismatch: got (string) but expected 'ptr'"
line: 20 line: 20
disabled: true
""" """
import typetraits import typetraits

View file

@ -0,0 +1,11 @@
discard """
errormsg: "'typedesc' metatype is not valid here; typed '=' instead of ':'?"
"""
var x = int
echo x

Some files were not shown because too many files have changed in this diff Show more